public static void TraceOperationCreation(Task task, string operationName) { DebuggerSupport.TraceOperationCreation(CausalityTraceLevel.Required, task, operationName, 0); }
private static unsafe Action GetCompletionActionHelper( ref Action cachedMoveNextAction, ref byte stateMachineAddress, EETypePtr stateMachineType, Task taskIfDebuggingEnabled) { // Alert a listening debugger that we can't make forward progress unless it slips threads. // If we don't do this, and a method that uses "await foo;" is invoked through funceval, // we could end up hooking up a callback to push forward the async method's state machine, // the debugger would then abort the funceval after it takes too long, and then continuing // execution could result in another callback being hooked up. At that point we have // multiple callbacks registered to push the state machine, which could result in bad behavior. //Debugger.NotifyOfCrossThreadDependency(); MoveNextRunner runner; if (cachedMoveNextAction != null) { Debug.Assert(cachedMoveNextAction.Target is MoveNextRunner); runner = (MoveNextRunner)cachedMoveNextAction.Target; runner.m_executionContext = ExecutionContext.Capture(); return(cachedMoveNextAction); } runner = new MoveNextRunner(); runner.m_executionContext = ExecutionContext.Capture(); cachedMoveNextAction = runner.CallMoveNext; if (taskIfDebuggingEnabled != null) { runner.m_task = taskIfDebuggingEnabled; if (DebuggerSupport.LoggingOn) { IntPtr eeType = stateMachineType.RawValue; DebuggerSupport.TraceOperationCreation(CausalityTraceLevel.Required, taskIfDebuggingEnabled, "Async: " + eeType.ToString("x"), 0); } DebuggerSupport.AddToActiveTasks(taskIfDebuggingEnabled); } // // If the state machine is a value type, we need to box it now. // IAsyncStateMachine boxedStateMachine; if (stateMachineType.IsValueType) { object boxed = RuntimeImports.RhBox(stateMachineType, ref stateMachineAddress); Debug.Assert(boxed is IAsyncStateMachine); boxedStateMachine = Unsafe.As <IAsyncStateMachine>(boxed); } else { boxedStateMachine = Unsafe.As <byte, IAsyncStateMachine>(ref stateMachineAddress); } runner.m_stateMachine = boxedStateMachine; #if DEBUG // // In debug builds, we'll go ahead and call SetStateMachine, even though all of our initialization is done. // This way we'll keep forcing state machine implementations to keep the behavior needed by the CLR. // boxedStateMachine.SetStateMachine(boxedStateMachine); #endif // All done! return(cachedMoveNextAction); }