private bool CaptureOrComplete(ref ExecutionContext cachedContext, bool returnContext)
{
if ((_flags & StateFlags.PostBlockStarted) == 0)
{
NetEventSource.Fail(this, "Called without calling StartPostingAsyncOp.");
}
// See if we're going to need to capture the context.
bool capturingContext = AsyncCallback != null || (_flags & StateFlags.CaptureContext) != 0;
// Peek if we've already completed, but don't fix CompletedSynchronously yet
// Capture the identity if requested, unless we're going to capture the context anyway, unless
// capturing the context won't be sufficient.
if ((_flags & StateFlags.CaptureIdentity) != 0 && !InternalPeekCompleted && (!capturingContext))
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "starting identity capture");
SafeCaptureIdentity();
}
// No need to flow if there's no callback, unless it's been specifically requested.
// Note that Capture() can return null, for example if SuppressFlow() is in effect.
if (capturingContext && !InternalPeekCompleted)
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "starting capture");
if (cachedContext == null)
{
cachedContext = ExecutionContext.Capture();
}
if (cachedContext != null)
{
if (!returnContext)
{
_context = cachedContext;
cachedContext = null;
}
else
{
_context = cachedContext;
}
}
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"_context:{_context}");
}
else
{
// Otherwise we have to have completed synchronously, or not needed the context.
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Skipping capture");
cachedContext = null;
if (AsyncCallback != null && !CompletedSynchronously)
{
NetEventSource.Fail(this, "Didn't capture context, but didn't complete synchronously!");
}
}
// Now we want to see for sure what to do. We might have just captured the context for no reason.
// This has to be the first time the state has been queried "for real" (apart from InvokeCallback)
// to guarantee synchronization with Complete() (otherwise, Complete() could try to call the
// callback without the context having been gotten).
DebugProtectState(false);
if (CompletedSynchronously)
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Completing synchronously");
base.Complete(IntPtr.Zero);
return true;
}
return false;
}