private static Action GetActionLogDelegate(int continuationId, Action action) { return(() => { Guid activityId = TplEventSource.CreateGuidForTaskID(continuationId); System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(activityId, out Guid savedActivityId); try { action(); } finally { System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(savedActivityId); } }); }
/// <summary>Calls InvokeOrPostAction(false) on the supplied SynchronizationContextAwaitTaskContinuation.</summary> /// <param name="state">The SynchronizationContextAwaitTaskContinuation.</param> private static void PostAction(object state) { var c = (SynchronizationContextAwaitTaskContinuation)state; TplEventSource log = TplEventSource.Log; if (log.TasksSetActivityIds && c.m_continuationId != 0) { c.m_syncContext.Post(s_postCallback, GetActionLogDelegate(c.m_continuationId, c.m_action)); } else { c.m_syncContext.Post(s_postCallback, c.m_action); // s_postCallback is manually cached, as the compiler won't in a SecurityCritical method } }
/// <summary>Inlines or schedules the continuation.</summary> /// <param name="task">The antecedent task, which is ignored.</param> /// <param name="canInlineContinuationTask">true if inlining is permitted; otherwise, false.</param> internal sealed override void Run(Task task, bool canInlineContinuationTask) { // If we're allowed to inline, run the action on this thread. if (canInlineContinuationTask && m_syncContext == SynchronizationContext.Current) { RunCallback(GetInvokeActionCallback(), m_action, ref Task.t_currentTask); } // Otherwise, Post the action back to the SynchronizationContext. else { TplEventSource log = TplEventSource.Log; if (log.IsEnabled()) { m_continuationId = Task.NewId(); log.AwaitTaskContinuationScheduled((task.ExecutingTaskScheduler ?? TaskScheduler.Default).Id, task.Id, m_continuationId); } RunCallback(GetPostActionCallback(), this, ref Task.t_currentTask); } // Any exceptions will be handled by RunCallback. }