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;
}
}