// Token: 0x06004044 RID: 16452 RVA: 0x000EF724 File Offset: 0x000ED924 private bool TrySetFromTask(Task task, bool lookForOce) { if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, base.Id, CausalityRelation.Join); } bool result = false; switch (task.Status) { case TaskStatus.RanToCompletion: { Task <TResult> task2 = task as Task <TResult>; if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, base.Id, AsyncCausalityStatus.Completed); } if (Task.s_asyncDebuggingEnabled) { Task.RemoveFromActiveTasks(base.Id); } result = base.TrySetResult((task2 != null) ? task2.Result : default(TResult)); break; } case TaskStatus.Canceled: result = base.TrySetCanceled(task.CancellationToken, task.GetCancellationExceptionDispatchInfo()); break; case TaskStatus.Faulted: { ReadOnlyCollection <ExceptionDispatchInfo> exceptionDispatchInfos = task.GetExceptionDispatchInfos(); ExceptionDispatchInfo exceptionDispatchInfo; OperationCanceledException ex; if (lookForOce && exceptionDispatchInfos.Count > 0 && (exceptionDispatchInfo = exceptionDispatchInfos[0]) != null && (ex = (exceptionDispatchInfo.SourceException as OperationCanceledException)) != null) { result = base.TrySetCanceled(ex.CancellationToken, exceptionDispatchInfo); } else { result = base.TrySetException(exceptionDispatchInfos); } break; } } return(result); }
/// <summary>Initializes a new continuation.</summary> /// <param name="task">The task to be activated.</param> /// <param name="options">The continuation options.</param> /// <param name="scheduler">The scheduler to use for the continuation.</param> internal StandardTaskContinuation(Task task, TaskContinuationOptions options, TaskScheduler scheduler) { Contract.Requires(task != null, "TaskContinuation ctor: task is null"); Contract.Requires(scheduler != null, "TaskContinuation ctor: scheduler is null"); m_task = task; m_options = options; m_taskScheduler = scheduler; if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, m_task.Id, "Task.ContinueWith: " + ((Delegate)task.m_action).Method.Name, 0); } if (Task.s_asyncDebuggingEnabled) { Task.AddToActiveTasks(m_task); } }
/// <summary>Initializes a new continuation.</summary> /// <param name="task">The task to be activated.</param> /// <param name="options">The continuation options.</param> /// <param name="scheduler">The scheduler to use for the continuation.</param> internal StandardTaskContinuation(Task task, TaskContinuationOptions options, TaskScheduler scheduler) { Debug.Assert(task != null, "TaskContinuation ctor: task is null"); Debug.Assert(scheduler != null, "TaskContinuation ctor: scheduler is null"); m_task = task; m_options = options; m_taskScheduler = scheduler; if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationCreation(m_task, "Task.ContinueWith: " + task.m_action.Method.Name); } if (Task.s_asyncDebuggingEnabled) { Task.AddToActiveTasks(m_task); } }
void ExecuteWithThreadLocal(ref Task currentTaskSlot) { // Remember the current task so we can restore it after running, and then Task previousTask = currentTaskSlot; try { // place the current task into TLS. currentTaskSlot = this; ExecutionContext ec = CapturedContext; if (ec == null) { // No context, just run the task directly. Execute(); } else { // Run the task. We need a simple shim that converts the // object back into a Task object, so that we can Execute it. // Lazily initialize the callback delegate; benign ---- var callback = s_ecCallback; if (callback == null) { s_ecCallback = callback = new ContextCallback(ExecutionContextCallback); } #if PFX_LEGACY_3_5 ExecutionContext.Run(ec, callback, this); #else ExecutionContext.Run(ec, callback, this, true); #endif } if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceSynchronousWorkCompletion(CausalityTraceLevel.Required, CausalitySynchronousWork.Execution); } Finish(true); } finally { currentTaskSlot = previousTask; } }
internal static void TraceOperationRelation(CausalityTraceLevel traceLevel, int taskId, CausalityRelation relation) { try { if ((AsyncCausalityTracer.f_LoggingOn & AsyncCausalityTracer.Loggers.ETW) != (AsyncCausalityTracer.Loggers) 0) { TplEtwProvider.Log.TraceOperationRelation(taskId, relation); } if ((AsyncCausalityTracer.f_LoggingOn & AsyncCausalityTracer.Loggers.CausalityTracer) != (AsyncCausalityTracer.Loggers) 0) { AsyncCausalityTracer.s_TracerFactory.TraceOperationRelation((CausalityTraceLevel)traceLevel, CausalitySource.Library, AsyncCausalityTracer.s_PlatformId, AsyncCausalityTracer.GetOperationId((uint)taskId), (CausalityRelation)relation); } } catch (Exception ex) { AsyncCausalityTracer.LogAndDisable(ex); } }
internal static void TraceOperationCreation(CausalityTraceLevel traceLevel, int taskId, string operationName, ulong relatedContext) { try { if ((AsyncCausalityTracer.f_LoggingOn & AsyncCausalityTracer.Loggers.ETW) != (AsyncCausalityTracer.Loggers) 0) { TplEtwProvider.Log.TraceOperationBegin(taskId, operationName, (long)relatedContext); } if ((AsyncCausalityTracer.f_LoggingOn & AsyncCausalityTracer.Loggers.CausalityTracer) != (AsyncCausalityTracer.Loggers) 0) { AsyncCausalityTracer.s_TracerFactory.TraceOperationCreation((CausalityTraceLevel)traceLevel, CausalitySource.Library, AsyncCausalityTracer.s_PlatformId, AsyncCausalityTracer.GetOperationId((uint)taskId), operationName, relatedContext); } } catch (Exception ex) { AsyncCausalityTracer.LogAndDisable(ex); } }
internal static void TraceSynchronousWorkCompletion(CausalityTraceLevel traceLevel, CausalitySynchronousWork work) { try { if ((AsyncCausalityTracer.f_LoggingOn & AsyncCausalityTracer.Loggers.ETW) != (AsyncCausalityTracer.Loggers) 0) { TplEtwProvider.Log.TraceSynchronousWorkEnd(work); } if ((AsyncCausalityTracer.f_LoggingOn & AsyncCausalityTracer.Loggers.CausalityTracer) != (AsyncCausalityTracer.Loggers) 0) { AsyncCausalityTracer.s_TracerFactory.TraceSynchronousWorkCompletion((CausalityTraceLevel)traceLevel, CausalitySource.Library, (CausalitySynchronousWork)work); } } catch (Exception ex) { AsyncCausalityTracer.LogAndDisable(ex); } }
internal static void TraceSynchronousWorkStart(CausalityTraceLevel traceLevel, int taskId, CausalitySynchronousWork work) { try { if ((AsyncCausalityTracer.f_LoggingOn & AsyncCausalityTracer.Loggers.ETW) != (AsyncCausalityTracer.Loggers) 0) { TplEtwProvider.Log.TraceSynchronousWorkBegin(taskId, work); } if ((AsyncCausalityTracer.f_LoggingOn & AsyncCausalityTracer.Loggers.CausalityTracer) != (AsyncCausalityTracer.Loggers) 0) { AsyncCausalityTracer.s_TracerFactory.TraceSynchronousWorkStart((CausalityTraceLevel)traceLevel, CausalitySource.Library, AsyncCausalityTracer.s_PlatformId, AsyncCausalityTracer.GetOperationId((uint)taskId), (CausalitySynchronousWork)work); } } catch (Exception ex) { AsyncCausalityTracer.LogAndDisable(ex); } }
internal static void TraceOperationCompletion(CausalityTraceLevel traceLevel, int taskId, AsyncCausalityStatus status) { try { if ((AsyncCausalityTracer.f_LoggingOn & AsyncCausalityTracer.Loggers.ETW) != (AsyncCausalityTracer.Loggers) 0) { TplEtwProvider.Log.TraceOperationEnd(taskId, status); } if ((AsyncCausalityTracer.f_LoggingOn & AsyncCausalityTracer.Loggers.CausalityTracer) == (AsyncCausalityTracer.Loggers) 0) { return; } AsyncCausalityTracer.s_TracerFactory.TraceOperationCompletion((Windows.Foundation.Diagnostics.CausalityTraceLevel)traceLevel, CausalitySource.Library, AsyncCausalityTracer.s_PlatformId, AsyncCausalityTracer.GetOperationId((uint)taskId), (Windows.Foundation.Diagnostics.AsyncCausalityStatus)status); } catch (Exception ex) { AsyncCausalityTracer.LogAndDisable(ex); } }
// Token: 0x0600403F RID: 16447 RVA: 0x000EF5B8 File Offset: 0x000ED7B8 public UnwrapPromise(Task outerTask, bool lookForOce) : base(null, outerTask.CreationOptions & TaskCreationOptions.AttachedToParent) { this._lookForOce = lookForOce; this._state = 0; if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, base.Id, "Task.Unwrap", 0UL); } if (Task.s_asyncDebuggingEnabled) { Task.AddToActiveTasks(this); } if (outerTask.IsCompleted) { this.ProcessCompletedOuterTask(outerTask); return; } outerTask.AddCompletionAction(this); }
// Token: 0x0600415C RID: 16732 RVA: 0x000F2FD8 File Offset: 0x000F11D8 protected override void OnEventCommand(EventCommandEventArgs command) { if (command.Command == EventCommand.Enable) { AsyncCausalityTracer.EnableToETW(true); } else if (command.Command == EventCommand.Disable) { AsyncCausalityTracer.EnableToETW(false); } if (base.IsEnabled(EventLevel.Informational, (EventKeywords)128L)) { ActivityTracker.Instance.Enable(); } else { this.TasksSetActivityIds = base.IsEnabled(EventLevel.Informational, (EventKeywords)65536L); } this.Debug = base.IsEnabled(EventLevel.Informational, (EventKeywords)131072L); this.DebugActivityId = base.IsEnabled(EventLevel.Informational, (EventKeywords)262144L); }
static AsyncCausalityTracer() { if (!Environment.IsWinRTSupported) { return; } string activatableClassId = "Windows.Foundation.Diagnostics.AsyncCausalityTracer"; Guid iid = new Guid(1350896422, (short)9854, (short)17691, (byte)168, (byte)144, (byte)171, (byte)106, (byte)55, (byte)2, (byte)69, (byte)238); object factory = (object)null; try { if (UnsafeNativeMethods.RoGetActivationFactory(activatableClassId, ref iid, out factory) < 0 || factory == null) { return; } AsyncCausalityTracer.s_TracerFactory = (IAsyncCausalityTracerStatics)factory; AsyncCausalityTracer.s_TracerFactory.add_TracingStatusChanged(new EventHandler <TracingStatusChangedEventArgs>(AsyncCausalityTracer.TracingStatusChangedHandler)); } catch (Exception ex) { AsyncCausalityTracer.LogAndDisable(ex); } }
private bool TrySetFromTask(Task task, bool lookForOce) { if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join); } bool flag = false; switch (task.Status) { case TaskStatus.RanToCompletion: Task <TResult> task1 = task as Task <TResult>; if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed); } if (Task.s_asyncDebuggingEnabled) { Task.RemoveFromActiveTasks(this.Id); } flag = this.TrySetResult(task1 != null ? task1.Result : default(TResult)); break; case TaskStatus.Canceled: flag = this.TrySetCanceled(task.CancellationToken, (object)task.GetCancellationExceptionDispatchInfo()); break; case TaskStatus.Faulted: ReadOnlyCollection <ExceptionDispatchInfo> exceptionDispatchInfos = task.GetExceptionDispatchInfos(); ExceptionDispatchInfo exceptionDispatchInfo; OperationCanceledException canceledException; flag = !lookForOce || exceptionDispatchInfos.Count <= 0 || ((exceptionDispatchInfo = exceptionDispatchInfos[0]) == null || (canceledException = exceptionDispatchInfo.SourceException as OperationCanceledException) == null) ? this.TrySetException((object)exceptionDispatchInfos) : this.TrySetCanceled(canceledException.CancellationToken, (object)exceptionDispatchInfo); break; } return(flag); }
static AsyncCausalityTracer() { if (!Environment.IsWinRTSupported) { return; } string activatableClassId = "Windows.Foundation.Diagnostics.AsyncCausalityTracer"; Guid guid = new Guid(1350896422, 9854, 17691, 168, 144, 171, 106, 55, 2, 69, 238); object obj = null; try { int num = Microsoft.Win32.UnsafeNativeMethods.RoGetActivationFactory(activatableClassId, ref guid, out obj); if (num >= 0 && obj != null) { AsyncCausalityTracer.s_TracerFactory = (IAsyncCausalityTracerStatics)obj; EventRegistrationToken eventRegistrationToken = AsyncCausalityTracer.s_TracerFactory.add_TracingStatusChanged(new EventHandler <TracingStatusChangedEventArgs>(AsyncCausalityTracer.TracingStatusChangedHandler)); } } catch (Exception ex) { AsyncCausalityTracer.LogAndDisable(ex); } }
/// <summary> /// Get callbacks when the ETW sends us commands` /// </summary> protected override void OnEventCommand(EventCommandEventArgs command) { // To get the AsyncCausality events, we need to inform the AsyncCausalityTracer if (command.Command == EventCommand.Enable) { AsyncCausalityTracer.EnableToETW(true); } else if (command.Command == EventCommand.Disable) { AsyncCausalityTracer.EnableToETW(false); } if (IsEnabled(EventLevel.Informational, Keywords.TasksFlowActivityIds)) { ActivityTracker.Instance.Enable(); } else { TasksSetActivityIds = IsEnabled(EventLevel.Informational, Keywords.TasksSetActivityIds); } Debug = IsEnabled(EventLevel.Informational, Keywords.Debug); DebugActivityId = IsEnabled(EventLevel.Informational, Keywords.DebugActivityId); }
/// <summary>Invokes the continuation for the target completion task.</summary> /// <param name="completedTask">The completed task.</param> /// <param name="canInlineContinuationTask">Whether the continuation can be inlined.</param> internal override void Run(Task completedTask, bool canInlineContinuationTask) { Debug.Assert(completedTask != null); Debug.Assert(completedTask.IsCompleted, "ContinuationTask.Run(): completedTask not completed"); Task?continuationTask = m_task; Debug.Assert(continuationTask != null); m_task = null; // Check if the completion status of the task works with the desired // activation criteria of the TaskContinuationOptions. TaskContinuationOptions options = m_options; bool isRightKind = completedTask.IsCompletedSuccessfully ? (options & TaskContinuationOptions.NotOnRanToCompletion) == 0 : (completedTask.IsCanceled ? (options & TaskContinuationOptions.NotOnCanceled) == 0 : (options & TaskContinuationOptions.NotOnFaulted) == 0); // If the completion status is allowed, run the continuation. if (isRightKind) { // If the task was cancel before running (e.g a ContinueWhenAll with a cancelled caancelation token) // we will still flow it to ScheduleAndStart() were it will check the status before running // We check here to avoid faulty logs that contain a join event to an operation that was already set as completed. if (!continuationTask.IsCanceled && AsyncCausalityTracer.LoggingOn) { // Log now that we are sure that this continuation is being ran AsyncCausalityTracer.TraceOperationRelation(continuationTask, CausalityRelation.AssignDelegate); } continuationTask.m_taskScheduler = m_taskScheduler; // Either run directly or just queue it up for execution, depending // on whether synchronous or asynchronous execution is wanted. if (canInlineContinuationTask && // inlining is allowed by the caller (options & TaskContinuationOptions.ExecuteSynchronously) != 0) // synchronous execution was requested by the continuation's creator { InlineIfPossibleOrElseQueue(continuationTask, needsProtection: true); } else { try { continuationTask.ScheduleAndStart(needsProtection: true); } catch (TaskSchedulerException) { // No further action is necessary -- ScheduleAndStart() already transitioned the // task to faulted. But we want to make sure that no exception is thrown from here. } } } else { // Otherwise, the final state of this task does not match the desired continuation activation criteria; cancel it to denote this. Task.ContingentProperties?cp = continuationTask.m_contingentProperties; // no need to volatile read, as we only care about the token, which is only assignable at construction if (cp is null || cp.m_cancellationToken == default) { // With no cancellation token, use an optimized path that doesn't need to account for concurrent completion. // This is primarily valuable for continuations created with TaskContinuationOptions.NotOn* options, where // we'll cancel the continuation if it's not needed. continuationTask.InternalCancelContinueWithInitialState(); }
/// <summary>Completes the task from the completed asynchronous operation.</summary> /// <param name="asyncInfo">The asynchronous operation.</param> /// <param name="getResultsFunction">A function used to retrieve the TResult from the async operation; may be null.</param> /// <param name="asyncStatus">The status of the asynchronous operation.</param> private void Complete(IAsyncInfo asyncInfo, Func <IAsyncInfo, TResult> getResultsFunction, AsyncStatus asyncStatus) { if (asyncInfo == null) { throw new ArgumentNullException(nameof(asyncInfo)); } Contract.EndContractBlock(); if (System.Threading.Tasks.Task.s_asyncDebuggingEnabled) { System.Threading.Tasks.Task.RemoveFromActiveTasks(base.Task.Id); } try { Debug.Assert(asyncInfo.Status == asyncStatus, "asyncInfo.Status does not match asyncStatus; are we dealing with a faulty IAsyncInfo implementation?"); // Assuming a correct underlying implementation, the task should not have been // completed yet. If it is completed, we shouldn't try to do any further work // with the operation or the task, as something is horked. bool taskAlreadyCompleted = Task.IsCompleted; Debug.Assert(!taskAlreadyCompleted, "Expected the task to not yet be completed."); if (taskAlreadyCompleted) { throw new InvalidOperationException(SR.InvalidOperation_InvalidAsyncCompletion); } // Clean up our registration with the cancellation token, noting that we're now in the process of cleaning up. CancellationTokenRegistration ctr; lock (StateLock) { _completing = true; ctr = _ctr; // under lock to avoid torn reads _ctr = default(CancellationTokenRegistration); } ctr.Unregister(); // It's ok if we end up unregistering a not-initialized registration; it'll just be a nop. try { // Find out how the async operation completed. It must be in a terminal state. bool terminalState = asyncStatus == AsyncStatus.Completed || asyncStatus == AsyncStatus.Canceled || asyncStatus == AsyncStatus.Error; Debug.Assert(terminalState, "The async operation should be in a terminal state."); if (!terminalState) { throw new InvalidOperationException(SR.InvalidOperation_InvalidAsyncCompletion); } // Retrieve the completion data from the IAsyncInfo. TResult result = default(TResult); Exception error = null; if (asyncStatus == AsyncStatus.Error) { error = asyncInfo.ErrorCode; // Defend against a faulty IAsyncInfo implementation: if (error == null) { Debug.Assert(false, "IAsyncInfo.Status == Error, but ErrorCode returns a null Exception (implying S_OK)."); error = new InvalidOperationException(SR.InvalidOperation_InvalidAsyncCompletion); } else { error = RestrictedErrorInfoHelper.AttachRestrictedErrorInfo(asyncInfo.ErrorCode); } } else if (asyncStatus == AsyncStatus.Completed && getResultsFunction != null) { try { result = getResultsFunction(asyncInfo); } catch (Exception resultsEx) { // According to the WinRT team, this can happen in some egde cases, such as marshalling errors in GetResults. error = resultsEx; asyncStatus = AsyncStatus.Error; } } // Nothing to retrieve for a canceled operation or for a completed operation with no result. // Complete the task based on the previously retrieved results: bool success = false; switch (asyncStatus) { case AsyncStatus.Completed: if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, base.Task.Id, AsyncCausalityStatus.Completed); } success = base.TrySetResult(result); break; case AsyncStatus.Error: Debug.Assert(error != null, "The error should have been retrieved previously."); success = base.TrySetException(error); break; case AsyncStatus.Canceled: success = base.TrySetCanceled(_ct.IsCancellationRequested ? _ct : new CancellationToken(true)); break; } Debug.Assert(success, "Expected the outcome to be successfully transfered to the task."); } catch (Exception exc) { // This really shouldn't happen, but could in a variety of misuse cases // such as a faulty underlying IAsyncInfo implementation. Debug.Assert(false, string.Format("Unexpected exception in Complete: {0}", exc.ToString())); if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, base.Task.Id, AsyncCausalityStatus.Error); } // For these cases, store the exception into the task so that it makes its way // back to the caller. Only if something went horribly wrong and we can't store the exception // do we allow it to be propagated out to the invoker of the Completed handler. if (!base.TrySetException(exc)) { Debug.Assert(false, "The task was already completed and thus the exception couldn't be stored."); throw; } } } finally { // We may be called on an STA thread which we don't own, so make sure that the RCW is released right // away. Otherwise, if we leave it up to the finalizer, the apartment may already be gone. if (Marshal.IsComObject(asyncInfo)) { Marshal.ReleaseComObject(asyncInfo); } } } // private void Complete(..)