<Compile Include="$(BclSourcesRoot)\System\Threading\Monitor.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Overlapped.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\SynchronizationContext.cs" />
- <Compile Include="$(BclSourcesRoot)\System\Threading\Tasks\TaskContinuation.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Thread.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\ThreadPool.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Timer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\Task.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskCanceledException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskCompletionSource.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskContinuation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskExceptionHolder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskFactory.cs" />
using System.Diagnostics.Tracing;
using System.Reflection;
using System.Runtime.ExceptionServices;
-#if FEATURE_COMINTEROP
-using System.Runtime.InteropServices.WindowsRuntime;
-#endif // FEATURE_COMINTEROP
using System.Threading;
using System.Threading.Tasks;
using System.Text;
using Internal.Runtime.CompilerServices;
-using Internal.Runtime.Augments;
#if CORERT
using Thread = Internal.Runtime.Augments.RuntimeThread;
// and decrement its outstanding operation count.
try
{
- AsyncMethodBuilderCore.ThrowAsync(exception, targetContext: _synchronizationContext);
+ System.Threading.Tasks.Task.ThrowAsync(exception, targetContext: _synchronizationContext);
}
finally
{
// Otherwise, queue the exception to be thrown on the ThreadPool. This will
// result in a crash unless legacy exception behavior is enabled by a config
// file or a CLR host.
- AsyncMethodBuilderCore.ThrowAsync(exception, targetContext: null);
+ System.Threading.Tasks.Task.ThrowAsync(exception, targetContext: null);
}
// The exception was propagated already; we don't need or want to fault the builder, just mark it as completed.
{
// If the interaction with the SynchronizationContext goes awry,
// fall back to propagating on the ThreadPool.
- AsyncMethodBuilderCore.ThrowAsync(exc, targetContext: null);
+ Task.ThrowAsync(exc, targetContext: null);
}
}
}
catch (Exception e)
{
- AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null);
+ System.Threading.Tasks.Task.ThrowAsync(e, targetContext: null);
}
}
// exceptions well at that location in the state machine, especially if the exception may occur
// after the ValueTaskAwaiter already successfully hooked up the callback, in which case it's possible
// two different flows of execution could end up happening in the same async method call.
- AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null);
+ System.Threading.Tasks.Task.ThrowAsync(e, targetContext: null);
}
}
else
}
catch (Exception e)
{
- AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null);
+ System.Threading.Tasks.Task.ThrowAsync(e, targetContext: null);
}
}
}
internal static Task TryGetContinuationTask(Action continuation) =>
(continuation?.Target as ContinuationWrapper)?._innerTask;
- /// <summary>Throws the exception on the ThreadPool.</summary>
- /// <param name="exception">The exception to propagate.</param>
- /// <param name="targetContext">The target context on which to propagate the exception. Null to use the ThreadPool.</param>
- internal static void ThrowAsync(Exception exception, SynchronizationContext targetContext)
- {
- // Capture the exception into an ExceptionDispatchInfo so that its
- // stack trace and Watson bucket info will be preserved
- var edi = ExceptionDispatchInfo.Capture(exception);
-
- // If the user supplied a SynchronizationContext...
- if (targetContext != null)
- {
- try
- {
- // Post the throwing of the exception to that context, and return.
- targetContext.Post(state => ((ExceptionDispatchInfo)state).Throw(), edi);
- return;
- }
- catch (Exception postException)
- {
- // If something goes horribly wrong in the Post, we'll
- // propagate both exceptions on the ThreadPool
- edi = ExceptionDispatchInfo.Capture(new AggregateException(exception, postException));
- }
- }
-
-#if CORERT
- RuntimeAugments.ReportUnhandledException(edi.SourceException);
-#else
-
-#if FEATURE_COMINTEROP
- // If we have the new error reporting APIs, report this error.
- if (WindowsRuntimeMarshal.ReportUnhandledError(edi.SourceException))
- return;
-#endif // FEATURE_COMINTEROP
-
- // Propagate the exception(s) on the ThreadPool
- ThreadPool.QueueUserWorkItem(state => ((ExceptionDispatchInfo)state).Throw(), edi);
-
-#endif // CORERT
- }
-
/// <summary>
/// Logically we pass just an Action (delegate) to a task for its action to 'ContinueWith' when it completes.
/// However debuggers and profilers need more information about what that action is. (In particular what
internal const int TASK_STATE_RAN_TO_COMPLETION = 0x1000000; //bin: 0000 0001 0000 0000 0000 0000 0000 0000
internal const int TASK_STATE_WAITINGFORACTIVATION = 0x2000000; //bin: 0000 0010 0000 0000 0000 0000 0000 0000
internal const int TASK_STATE_COMPLETION_RESERVED = 0x4000000; //bin: 0000 0100 0000 0000 0000 0000 0000 0000
- internal const int TASK_STATE_THREAD_WAS_ABORTED = 0x8000000; //bin: 0000 1000 0000 0000 0000 0000 0000 0000
internal const int TASK_STATE_WAIT_COMPLETION_NOTIFICATION = 0x10000000; //bin: 0001 0000 0000 0000 0000 0000 0000 0000
//This could be moved to InternalTaskOptions enum
internal const int TASK_STATE_EXECUTIONCONTEXT_IS_NULL = 0x20000000; //bin: 0010 0000 0000 0000 0000 0000 0000 0000
}
catch (Exception e)
{
- // we 1) either received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown
- // 2) or a a ThreadAbortException, which we need to skip here, because it would already have been handled in Task.Execute
- if (!taskQueued && !(e is ThreadAbortException))
+ // we received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown
+ if (!taskQueued)
{
// We had a problem with TryRunInline() or QueueTask().
// Record the exception, marking ourselves as Completed/Faulted.
// And re-throw.
throw tse;
}
- // We had a problem with waiting or this is a thread abort. Just re-throw.
+ // We had a problem with waiting. Just re-throw.
else throw;
}
}
}
}
+ /// <summary>Throws the exception on the ThreadPool.</summary>
+ /// <param name="exception">The exception to propagate.</param>
+ /// <param name="targetContext">The target context on which to propagate the exception. Null to use the ThreadPool.</param>
+ internal static void ThrowAsync(Exception exception, SynchronizationContext targetContext)
+ {
+ // Capture the exception into an ExceptionDispatchInfo so that its
+ // stack trace and Watson bucket info will be preserved
+ var edi = ExceptionDispatchInfo.Capture(exception);
+
+ // If the user supplied a SynchronizationContext...
+ if (targetContext != null)
+ {
+ try
+ {
+ // Post the throwing of the exception to that context, and return.
+ targetContext.Post(state => ((ExceptionDispatchInfo)state).Throw(), edi);
+ return;
+ }
+ catch (Exception postException)
+ {
+ // If something goes horribly wrong in the Post, we'll
+ // propagate both exceptions on the ThreadPool
+ edi = ExceptionDispatchInfo.Capture(new AggregateException(exception, postException));
+ }
+ }
+
+#if CORERT
+ RuntimeAugments.ReportUnhandledException(edi.SourceException);
+#else
+
+#if FEATURE_COMINTEROP
+ // If we have the new error reporting APIs, report this error.
+ if (System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMarshal.ReportUnhandledError(edi.SourceException))
+ return;
+#endif
+
+ // Propagate the exception(s) on the ThreadPool
+ ThreadPool.QueueUserWorkItem(state => ((ExceptionDispatchInfo)state).Throw(), edi);
+
+#endif // CORERT
+ }
+
/// <summary>
/// Checks whether this is an attached task, and whether we are being called by the parent task.
/// And sets the TASK_STATE_EXCEPTIONOBSERVEDBYPARENT status flag based on that.
if (AsyncCausalityTracer.LoggingOn)
AsyncCausalityTracer.TraceSynchronousWorkStart(this, CausalitySynchronousWork.CompletionNotification);
- // Skip synchronous execution of continuations if this task's thread was aborted
- bool canInlineContinuations = !(((m_stateFlags & TASK_STATE_THREAD_WAS_ABORTED) != 0) ||
- ((m_stateFlags & (int)TaskCreationOptions.RunContinuationsAsynchronously) != 0));
+ bool canInlineContinuations = (m_stateFlags & (int)TaskCreationOptions.RunContinuationsAsynchronously) == 0;
switch (continuationObject)
{
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//
-//
-//
-// Implementation of task continuations, TaskContinuation, and its descendants.
-//
-// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
using System.Security;
using System.Diagnostics;
using System.Runtime.ExceptionServices;
using System.Runtime.CompilerServices;
-using System.Threading;
-#if FEATURE_COMINTEROP
-using System.Runtime.InteropServices.WindowsRuntime;
-#endif // FEATURE_COMINTEROP
+#if CORERT
+using Thread = Internal.Runtime.Augments.RuntimeThread;
+#endif
namespace System.Threading.Tasks
{
// Either TryRunInline() or QueueTask() threw an exception. Record the exception, marking the task as Faulted.
// However if it was a ThreadAbortException coming from TryRunInline we need to skip here,
// because it would already have been handled in Task.Execute()
- if (!(e is ThreadAbortException &&
- (task.m_stateFlags & Task.TASK_STATE_THREAD_WAS_ABORTED) != 0)) // this ensures TAEs from QueueTask will be wrapped in TSE
- {
- TaskSchedulerException tse = new TaskSchedulerException(e);
- task.AddException(tse);
- task.Finish(false);
- }
-
+ TaskSchedulerException tse = new TaskSchedulerException(e);
+ task.AddException(tse);
+ task.Finish(false);
// Don't re-throw.
}
}
+ //
+ // This helper routine is targeted by the debugger.
+ //
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
internal abstract Delegate[] GetDelegateContinuationsForDebugger();
}
internal sealed class SynchronizationContextAwaitTaskContinuation : AwaitTaskContinuation
{
/// <summary>SendOrPostCallback delegate to invoke the action.</summary>
- private readonly static SendOrPostCallback s_postCallback = state => ((Action)state)(); // can't use InvokeAction as it's SecurityCritical
+ private static readonly SendOrPostCallback s_postCallback = state => ((Action)state)(); // can't use InvokeAction as it's SecurityCritical
/// <summary>Cached delegate for PostAction</summary>
private static ContextCallback s_postActionCallback;
/// <summary>The context with which to run the action.</summary>
// The target scheduler may still deny us from executing on this thread, in which case this'll be queued.
var task = CreateTask(state =>
{
- try { ((Action)state)(); }
- catch (Exception exc) { ThrowAsyncIfNecessary(exc); }
+ try
+ {
+ ((Action)state)();
+ }
+ catch (Exception exception)
+ {
+ Task.ThrowAsync(exception, targetContext: null);
+ }
}, m_action, m_scheduler);
if (inlineIfPossible)
return;
}
- Guid savedActivityId = Guid.Empty;
+ Guid savedActivityId = default;
if (etwLog.TasksSetActivityIds && m_continuationId != 0)
{
Guid activityId = TplEtwProvider.CreateGuidForTaskID(m_continuationId);
ExecutionContext.RunInternal(context, callback, state);
}
}
- catch (Exception exc) // we explicitly do not request handling of dangerous exceptions like AVs
+ catch (Exception exception) // we explicitly do not request handling of dangerous exceptions like AVs
{
- ThrowAsyncIfNecessary(exc);
+ Task.ThrowAsync(exception, targetContext: null);
}
finally
{
}
catch (Exception exception)
{
- ThrowAsyncIfNecessary(exception);
+ Task.ThrowAsync(exception, targetContext: null);
}
finally
{
}
catch (Exception exception)
{
- ThrowAsyncIfNecessary(exception);
+ Task.ThrowAsync(exception, targetContext: null);
}
finally
{
ThreadPool.UnsafeQueueUserWorkItemInternal(atc, preferLocal: true);
}
- /// <summary>Throws the exception asynchronously on the ThreadPool.</summary>
- /// <param name="exc">The exception to throw.</param>
- protected static void ThrowAsyncIfNecessary(Exception exc)
- {
- // Awaits should never experience an exception (other than an TAE or ADUE),
- // unless a malicious user is explicitly passing a throwing action into the TaskAwaiter.
- // We don't want to allow the exception to propagate on this stack, as it'll emerge in random places,
- // and we can't fail fast, as that would allow for elevation of privilege.
- //
- // If unhandled error reporting APIs are available use those, otherwise since this
- // would have executed on the thread pool otherwise, let it propagate there.
-
- if (!(exc is ThreadAbortException))
- {
-#if FEATURE_COMINTEROP
- if (!WindowsRuntimeMarshal.ReportUnhandledError(exc))
-#endif // FEATURE_COMINTEROP
- {
- var edi = ExceptionDispatchInfo.Capture(exc);
- ThreadPool.QueueUserWorkItem(s => ((ExceptionDispatchInfo)s).Throw(), edi);
- }
- }
- }
-
internal override Delegate[] GetDelegateContinuationsForDebugger()
{
Debug.Assert(m_action != null);