private bool InvokeShouldMethodAndWaitForResults()

in src/Common/AzureLongRunningJob.cs [808:885]


        private bool InvokeShouldMethodAndWaitForResults(Func<Cmdlet, bool> shouldMethod, ShouldMethodType methodType, out Exception exceptionThrownOnCmdletThread)
        {

            bool methodResult = false;
            Exception closureSafeExceptionThrownOnCmdletThread = null;
            object resultsLock = new object();
            using (var gotResultEvent = new ManualResetEventSlim(false))
            {
                EventHandler<JobStateEventArgs> stateChangedEventHandler =
                    delegate (object sender, JobStateEventArgs eventArgs)
                    {
                        WriteDebug(string.Format(Resources.TraceHandleLROStateChange, eventArgs?.PreviousJobStateInfo?.State,
                            eventArgs?.JobStateInfo?.State, eventArgs?.PreviousJobStateInfo?.Reason));
                        if (eventArgs?.JobStateInfo?.State != JobState.Blocked && eventArgs?.PreviousJobStateInfo?.State == JobState.Blocked)
                        {
                            WriteDebug(Resources.TraceHandlerUnblockJob);
                            // if receive-job is called, unblock by executing delayed powershell actions
                            UnblockJob();
                        }

                        if (IsFailedOrCancelled(eventArgs.JobStateInfo.State) || eventArgs.JobStateInfo.State == JobState.Stopping)
                        {
                            WriteDebug(Resources.TraceHandlerUnblockJob);
                            lock (resultsLock)
                            {
                                closureSafeExceptionThrownOnCmdletThread = new OperationCanceledException();
                            }

                            gotResultEvent.Set();
                        }
                    };
                this.StateChanged += stateChangedEventHandler;
                Interlocked.MemoryBarrier();
                try
                {
                    stateChangedEventHandler(null, new JobStateEventArgs(this.JobStateInfo));
                    if (!gotResultEvent.IsSet)
                    {
                        WriteDebug(string.Format(Resources.TraceBlockLROThread, methodType));
                        ShouldMethodInvoker methodInvoker = new ShouldMethodInvoker
                        {
                            ShouldMethod = shouldMethod,
                            Finished = gotResultEvent,
                            SyncObject = resultsLock,
                            MethodType = methodType
                        };

                        BlockedActions.Enqueue(new ShouldMethodStreamItem(methodInvoker));
                        if (this.TryBlock())
                        {
                            gotResultEvent.Wait();
                            WriteDebug(string.Format(Resources.TraceUnblockLROThread, shouldMethod));
                            TryStart();
                            lock (resultsLock)
                            {
                                if (closureSafeExceptionThrownOnCmdletThread == null) // stateChangedEventHandler didn't set the results?  = ok to clobber results?
                                {
                                    closureSafeExceptionThrownOnCmdletThread = methodInvoker.ThrownException;
                                    methodResult = methodInvoker.MethodResult;
                                }
                            }
                        }
                    }
                }
                finally
                {
                    WriteDebug(string.Format(Resources.TraceRemoveLROEventHandler,
                        closureSafeExceptionThrownOnCmdletThread?.Message));
                    this.StateChanged -= stateChangedEventHandler;
                }
            }

            lock (resultsLock)
            {
                exceptionThrownOnCmdletThread = closureSafeExceptionThrownOnCmdletThread;
                return methodResult;
            }
        }