summaryrefslogtreecommitdiff
path: root/src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs')
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs226
1 files changed, 117 insertions, 109 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs
index 55fab9a5de..cc4c938f51 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#nullable enable
using System.Diagnostics;
namespace System.Threading.Tasks
@@ -32,27 +33,20 @@ namespace System.Threading.Tasks
// member variables
private CancellationToken m_defaultCancellationToken;
- private TaskScheduler m_defaultScheduler;
+ private TaskScheduler? m_defaultScheduler;
private TaskCreationOptions m_defaultCreationOptions;
private TaskContinuationOptions m_defaultContinuationOptions;
- private TaskScheduler DefaultScheduler
- {
- get
- {
- if (m_defaultScheduler == null) return TaskScheduler.Current;
- else return m_defaultScheduler;
- }
- }
+ private TaskScheduler DefaultScheduler => m_defaultScheduler ?? TaskScheduler.Current;
// sister method to above property -- avoids a TLS lookup
- private TaskScheduler GetDefaultScheduler(Task currTask)
+ private TaskScheduler GetDefaultScheduler(Task? currTask)
{
if (m_defaultScheduler != null) return m_defaultScheduler;
else if ((currTask != null)
&& ((currTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
)
- return currTask.ExecutingTaskScheduler;
+ return currTask.ExecutingTaskScheduler!; // a "current" task must be executing, which means it must have a scheduler
else return TaskScheduler.Default;
}
@@ -116,7 +110,7 @@ namespace System.Threading.Tasks
/// initialized to the current scheduler (see <see
/// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
/// </remarks>
- public TaskFactory(TaskScheduler scheduler) // null means to use TaskScheduler.Current
+ public TaskFactory(TaskScheduler? scheduler) // null means to use TaskScheduler.Current
: this(default, TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
{
}
@@ -187,7 +181,7 @@ namespace System.Threading.Tasks
/// current scheduler (see <see
/// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
/// </remarks>
- public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler? scheduler)
{
TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
TaskFactory.CheckCreationOptions(creationOptions);
@@ -221,7 +215,7 @@ namespace System.Threading.Tasks
/// If null, <see cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>
/// will be used.
/// </remarks>
- public TaskScheduler Scheduler { get { return m_defaultScheduler; } }
+ public TaskScheduler? Scheduler { get { return m_defaultScheduler; } }
/// <summary>
/// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions
@@ -264,7 +258,7 @@ namespace System.Threading.Tasks
/// </remarks>
public Task<TResult> StartNew(Func<TResult> function)
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
@@ -291,7 +285,7 @@ namespace System.Threading.Tasks
/// </remarks>
public Task<TResult> StartNew(Func<TResult> function, CancellationToken cancellationToken)
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, cancellationToken,
m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
@@ -320,7 +314,7 @@ namespace System.Threading.Tasks
/// </remarks>
public Task<TResult> StartNew(Func<TResult> function, TaskCreationOptions creationOptions)
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
@@ -383,9 +377,9 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew(Func<object, TResult> function, object state)
+ public Task<TResult> StartNew(Func<object?, TResult> function, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
@@ -412,9 +406,9 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew(Func<object, TResult> function, object state, CancellationToken cancellationToken)
+ public Task<TResult> StartNew(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
@@ -443,9 +437,9 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew(Func<object, TResult> function, object state, TaskCreationOptions creationOptions)
+ public Task<TResult> StartNew(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
@@ -485,7 +479,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew(Func<object, TResult> function, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
+ public Task<TResult> StartNew(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
return Task<TResult>.StartNew(Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken,
creationOptions, InternalTaskOptions.None, scheduler);
@@ -498,16 +492,16 @@ namespace System.Threading.Tasks
// Common core logic for FromAsync calls. This minimizes the chance of "drift" between overload implementations.
private static void FromAsyncCoreLogic(
IAsyncResult iar,
- Func<IAsyncResult, TResult> endFunction,
- Action<IAsyncResult> endAction,
+ Func<IAsyncResult, TResult>? endFunction,
+ Action<IAsyncResult>? endAction,
Task<TResult> promise,
bool requiresSynchronization)
{
Debug.Assert((endFunction != null) != (endAction != null), "Expected exactly one of endFunction/endAction to be non-null");
- Exception ex = null;
- OperationCanceledException oce = null;
- TResult result = default;
+ Exception? ex = null;
+ OperationCanceledException? oce = null;
+ TResult result = default!; // TODO-NULLABLE-GENERIC
try
{
@@ -517,7 +511,7 @@ namespace System.Threading.Tasks
}
else
{
- endAction(iar);
+ endAction!(iar);
}
}
catch (OperationCanceledException _oce) { oce = _oce; }
@@ -636,8 +630,8 @@ namespace System.Threading.Tasks
// method can access the logic w/o declaring a TaskFactory<TResult> instance.
internal static Task<TResult> FromAsyncImpl(
IAsyncResult asyncResult,
- Func<IAsyncResult, TResult> endFunction,
- Action<IAsyncResult> endAction,
+ Func<IAsyncResult, TResult>? endFunction,
+ Action<IAsyncResult>? endAction,
TaskCreationOptions creationOptions,
TaskScheduler scheduler)
{
@@ -654,7 +648,7 @@ namespace System.Threading.Tasks
TaskFactory.CheckFromAsyncOptions(creationOptions, false);
- Task<TResult> promise = new Task<TResult>((object)null, creationOptions);
+ Task<TResult> promise = new Task<TResult>((object?)null, creationOptions);
if (AsyncCausalityTracer.LoggingOn)
AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync");
@@ -669,7 +663,7 @@ namespace System.Threading.Tasks
{
FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: true);
}),
- (object)null, null,
+ (object?)null, null,
default, TaskCreationOptions.None, InternalTaskOptions.None, null);
if (AsyncCausalityTracer.LoggingOn)
@@ -678,9 +672,9 @@ namespace System.Threading.Tasks
if (Task.s_asyncDebuggingEnabled)
Task.AddToActiveTasks(t);
- if (asyncResult.IsCompleted)
+ if (asyncResult!.IsCompleted) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
- try { t.InternalRunSynchronously(scheduler, waitForCompletion: false); }
+ try { t.InternalRunSynchronously(scheduler!, waitForCompletion: false); } // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions
}
else
@@ -718,8 +712,8 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync(
- Func<AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endMethod, object state)
+ Func<AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
return FromAsyncImpl(beginMethod, endMethod, null, state, m_defaultCreationOptions);
}
@@ -747,17 +741,17 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync(
- Func<AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endMethod, object state, TaskCreationOptions creationOptions)
+ Func<AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
return FromAsyncImpl(beginMethod, endMethod, null, state, creationOptions);
}
// We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
// method can access the logic w/o declaring a TaskFactory<TResult> instance.
- internal static Task<TResult> FromAsyncImpl(Func<AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
- object state, TaskCreationOptions creationOptions)
+ internal static Task<TResult> FromAsyncImpl(Func<AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult>? endFunction, Action<IAsyncResult>? endAction,
+ object? state, TaskCreationOptions creationOptions)
{
if (beginMethod == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
@@ -772,7 +766,7 @@ namespace System.Threading.Tasks
Task<TResult> promise = new Task<TResult>(state, creationOptions);
if (AsyncCausalityTracer.LoggingOn)
- AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod.Method.Name);
+ AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
if (Task.s_asyncDebuggingEnabled)
Task.AddToActiveTasks(promise);
@@ -780,7 +774,7 @@ namespace System.Threading.Tasks
try
{
//if we don't require synchronization, a faster set result path is taken
- var asyncResult = beginMethod(iar =>
+ var asyncResult = beginMethod!(iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
if (!iar.CompletedSynchronously)
FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -829,9 +823,9 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TArg1>(
- Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
Func<IAsyncResult, TResult> endMethod,
- TArg1 arg1, object state)
+ TArg1 arg1, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, m_defaultCreationOptions);
}
@@ -863,18 +857,18 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TArg1>(
- Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
Func<IAsyncResult, TResult> endMethod,
- TArg1 arg1, object state, TaskCreationOptions creationOptions)
+ TArg1 arg1, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, creationOptions);
}
// We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
// method can access the logic w/o declaring a TaskFactory<TResult> instance.
- internal static Task<TResult> FromAsyncImpl<TArg1>(Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
- TArg1 arg1, object state, TaskCreationOptions creationOptions)
+ internal static Task<TResult> FromAsyncImpl<TArg1>(Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult>? endFunction, Action<IAsyncResult>? endAction,
+ TArg1 arg1, object? state, TaskCreationOptions creationOptions)
{
if (beginMethod == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
@@ -889,7 +883,7 @@ namespace System.Threading.Tasks
Task<TResult> promise = new Task<TResult>(state, creationOptions);
if (AsyncCausalityTracer.LoggingOn)
- AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod.Method.Name);
+ AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
if (Task.s_asyncDebuggingEnabled)
Task.AddToActiveTasks(promise);
@@ -897,7 +891,7 @@ namespace System.Threading.Tasks
try
{
//if we don't require synchronization, a faster set result path is taken
- var asyncResult = beginMethod(arg1, iar =>
+ var asyncResult = beginMethod!(arg1, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
if (!iar.CompletedSynchronously)
FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -950,9 +944,9 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TArg1, TArg2>(
- Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
Func<IAsyncResult, TResult> endMethod,
- TArg1 arg1, TArg2 arg2, object state)
+ TArg1 arg1, TArg2 arg2, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, m_defaultCreationOptions);
}
@@ -988,18 +982,18 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TArg1, TArg2>(
- Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
Func<IAsyncResult, TResult> endMethod,
- TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
+ TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, creationOptions);
}
// We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
// method can access the logic w/o declaring a TaskFactory<TResult> instance.
- internal static Task<TResult> FromAsyncImpl<TArg1, TArg2>(Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
- TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
+ internal static Task<TResult> FromAsyncImpl<TArg1, TArg2>(Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult>? endFunction, Action<IAsyncResult>? endAction,
+ TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
if (beginMethod == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
@@ -1014,7 +1008,7 @@ namespace System.Threading.Tasks
Task<TResult> promise = new Task<TResult>(state, creationOptions);
if (AsyncCausalityTracer.LoggingOn)
- AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod.Method.Name);
+ AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
if (Task.s_asyncDebuggingEnabled)
Task.AddToActiveTasks(promise);
@@ -1022,7 +1016,7 @@ namespace System.Threading.Tasks
try
{
//if we don't require synchronization, a faster set result path is taken
- var asyncResult = beginMethod(arg1, arg2, iar =>
+ var asyncResult = beginMethod!(arg1, arg2, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
if (!iar.CompletedSynchronously)
FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -1079,9 +1073,9 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TArg1, TArg2, TArg3>(
- Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
Func<IAsyncResult, TResult> endMethod,
- TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
+ TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state)
{
return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, m_defaultCreationOptions);
}
@@ -1121,18 +1115,18 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TArg1, TArg2, TArg3>(
- Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
Func<IAsyncResult, TResult> endMethod,
- TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+ TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state, TaskCreationOptions creationOptions)
{
return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, creationOptions);
}
// We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
// method can access the logic w/o declaring a TaskFactory<TResult> instance.
- internal static Task<TResult> FromAsyncImpl<TArg1, TArg2, TArg3>(Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
- TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+ internal static Task<TResult> FromAsyncImpl<TArg1, TArg2, TArg3>(Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult>? endFunction, Action<IAsyncResult>? endAction,
+ TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state, TaskCreationOptions creationOptions)
{
if (beginMethod == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
@@ -1147,7 +1141,7 @@ namespace System.Threading.Tasks
Task<TResult> promise = new Task<TResult>(state, creationOptions);
if (AsyncCausalityTracer.LoggingOn)
- AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod.Method.Name);
+ AsyncCausalityTracer.TraceOperationCreation(promise, "TaskFactory.FromAsync: " + beginMethod!.Method.Name); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
if (Task.s_asyncDebuggingEnabled)
Task.AddToActiveTasks(promise);
@@ -1155,7 +1149,7 @@ namespace System.Threading.Tasks
try
{
//if we don't require synchronization, a faster set result path is taken
- var asyncResult = beginMethod(arg1, arg2, arg3, iar =>
+ var asyncResult = beginMethod!(arg1, arg2, arg3, iar => // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
if (!iar.CompletedSynchronously)
FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
@@ -1237,7 +1231,7 @@ namespace System.Threading.Tasks
/// <summary>A reference to the object on which the begin/end methods are invoked.</summary>
private TInstance m_thisRef;
/// <summary>The end method.</summary>
- private Func<TInstance, IAsyncResult, TResult> m_endMethod;
+ private Func<TInstance, IAsyncResult, TResult>? m_endMethod;
/// <summary>Initializes the promise.</summary>
/// <param name="thisRef">A reference to the object on which the begin/end methods are invoked.</param>
@@ -1260,13 +1254,13 @@ namespace System.Threading.Tasks
// Validate argument
if (asyncResult == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.asyncResult);
- var promise = asyncResult.AsyncState as FromAsyncTrimPromise<TInstance>;
+ var promise = asyncResult!.AsyncState as FromAsyncTrimPromise<TInstance>; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
if (promise == null) ThrowHelper.ThrowArgumentException(ExceptionResource.InvalidOperation_WrongAsyncResultOrEndCalledMultiple, ExceptionArgument.asyncResult);
// Grab the relevant state and then null it out so that the task doesn't hold onto the state unnecessarily
- var thisRef = promise.m_thisRef;
+ var thisRef = promise!.m_thisRef; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
var endMethod = promise.m_endMethod;
- promise.m_thisRef = default;
+ promise.m_thisRef = default!; // TODO-NULLABLE-GENERIC
promise.m_endMethod = null;
if (endMethod == null) ThrowHelper.ThrowArgumentException(ExceptionResource.InvalidOperation_WrongAsyncResultOrEndCalledMultiple, ExceptionArgument.asyncResult);
@@ -1274,7 +1268,7 @@ namespace System.Threading.Tasks
// we'll instead complete the promise at the call site.
if (!asyncResult.CompletedSynchronously)
{
- promise.Complete(thisRef, endMethod, asyncResult, requiresSynchronization: true);
+ promise.Complete(thisRef, endMethod!, asyncResult, requiresSynchronization: true); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
}
@@ -1328,9 +1322,8 @@ namespace System.Threading.Tasks
private static Task<TResult> CreateCanceledTask(TaskContinuationOptions continuationOptions, CancellationToken ct)
{
TaskCreationOptions tco;
- InternalTaskOptions dontcare;
- Task.CreationOptionsFromContinuationOptions(continuationOptions, out tco, out dontcare);
- return new Task<TResult>(true, default, tco, ct);
+ Task.CreationOptionsFromContinuationOptions(continuationOptions, out tco, out _);
+ return new Task<TResult>(true, default!, tco, ct); // TODO-NULLABLE-GENERIC
}
//
@@ -1607,7 +1600,7 @@ namespace System.Threading.Tasks
// Core implementation of ContinueWhenAll -- the generic version
// Note: if you make any changes to this method, please do the same to the non-generic version too.
internal static Task<TResult> ContinueWhenAllImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
- Func<Task<TAntecedentResult>[], TResult> continuationFunction, Action<Task<TAntecedentResult>[]> continuationAction,
+ Func<Task<TAntecedentResult>[], TResult>? continuationFunction, Action<Task<TAntecedentResult>[]>? continuationAction,
TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
{
// check arguments
@@ -1618,7 +1611,7 @@ namespace System.Threading.Tasks
if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
// Check tasks array and make defensive copy
- Task<TAntecedentResult>[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy<TAntecedentResult>(tasks);
+ Task<TAntecedentResult>[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy<TAntecedentResult>(tasks!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
// Bail early if cancellation has been requested.
if (cancellationToken.IsCancellationRequested
@@ -1637,7 +1630,7 @@ namespace System.Threading.Tasks
return starter.ContinueWith<TResult>(
// use a cached delegate
GenericDelegateCache<TAntecedentResult, TResult>.CWAllFuncDelegate,
- continuationFunction, scheduler, cancellationToken, continuationOptions);
+ continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
else
{
@@ -1646,14 +1639,14 @@ namespace System.Threading.Tasks
return starter.ContinueWith<TResult>(
// use a cached delegate
GenericDelegateCache<TAntecedentResult, TResult>.CWAllActionDelegate,
- continuationAction, scheduler, cancellationToken, continuationOptions);
+ continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
}
// Core implementation of ContinueWhenAll -- the non-generic version
// Note: if you make any changes to this method, please do the same to the generic version too.
internal static Task<TResult> ContinueWhenAllImpl(Task[] tasks,
- Func<Task[], TResult> continuationFunction, Action<Task[]> continuationAction,
+ Func<Task[], TResult>? continuationFunction, Action<Task[]>? continuationAction,
TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
{
// check arguments
@@ -1664,7 +1657,7 @@ namespace System.Threading.Tasks
if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
// Check tasks array and make defensive copy
- Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks);
+ Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
// Bail early if cancellation has been requested.
if (cancellationToken.IsCancellationRequested
@@ -1687,9 +1680,10 @@ namespace System.Threading.Tasks
(completedTasks, state) =>
{
completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
+ Debug.Assert(state is Func<Task[], TResult>);
return ((Func<Task[], TResult>)state)(completedTasks.Result);
},
- continuationFunction, scheduler, cancellationToken, continuationOptions);
+ continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
else
{
@@ -1701,9 +1695,10 @@ namespace System.Threading.Tasks
(completedTasks, state) =>
{
completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
- ((Action<Task[]>)state)(completedTasks.Result); return default;
+ Debug.Assert(state is Action<Task[]>);
+ ((Action<Task[]>)state)(completedTasks.Result); return default!; // TODO-NULLABLE-GENERIC
},
- continuationAction, scheduler, cancellationToken, continuationOptions);
+ continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
}
@@ -1980,13 +1975,13 @@ namespace System.Threading.Tasks
// Core implementation of ContinueWhenAny, non-generic version
// Note: if you make any changes to this method, be sure to do the same to the generic version
internal static Task<TResult> ContinueWhenAnyImpl(Task[] tasks,
- Func<Task, TResult> continuationFunction, Action<Task> continuationAction,
+ Func<Task, TResult>? continuationFunction, Action<Task>? continuationAction,
TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
{
// check arguments
TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
- if (tasks.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks);
+ if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
//ArgumentNullException of continuationFunction or continuationAction is checked by the caller
Debug.Assert((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
@@ -2009,8 +2004,12 @@ namespace System.Threading.Tasks
return starter.ContinueWith(
//the following delegate avoids closure capture as much as possible
//completedTask.Result is the winning task; state == continuationAction
- (completedTask, state) => { return ((Func<Task, TResult>)state)(completedTask.Result); },
- continuationFunction, scheduler, cancellationToken, continuationOptions);
+ (completedTask, state) =>
+ {
+ Debug.Assert(state is Func<Task, TResult>);
+ return ((Func<Task, TResult>)state)(completedTask.Result);
+ },
+ continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
else
{
@@ -2018,8 +2017,13 @@ namespace System.Threading.Tasks
return starter.ContinueWith<TResult>(
//the following delegate avoids closure capture as much as possible
//completedTask.Result is the winning task; state == continuationAction
- (completedTask, state) => { ((Action<Task>)state)(completedTask.Result); return default; },
- continuationAction, scheduler, cancellationToken, continuationOptions);
+ (completedTask, state) =>
+ {
+ Debug.Assert(state is Action<Task>);
+ ((Action<Task>)state)(completedTask.Result);
+ return default!; // TODO-NULLABLE-GENERIC
+ },
+ continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
}
@@ -2027,13 +2031,13 @@ namespace System.Threading.Tasks
// Core implementation of ContinueWhenAny, generic version
// Note: if you make any changes to this method, be sure to do the same to the non-generic version
internal static Task<TResult> ContinueWhenAnyImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
- Func<Task<TAntecedentResult>, TResult> continuationFunction, Action<Task<TAntecedentResult>> continuationAction,
+ Func<Task<TAntecedentResult>, TResult>? continuationFunction, Action<Task<TAntecedentResult>>? continuationAction,
TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
{
// check arguments
TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
- if (tasks.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks);
+ if (tasks!.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
//ArgumentNullException of continuationFunction or continuationAction is checked by the caller
Debug.Assert((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
@@ -2055,7 +2059,7 @@ namespace System.Threading.Tasks
return starter.ContinueWith<TResult>(
// Use a cached delegate
GenericDelegateCache<TAntecedentResult, TResult>.CWAnyFuncDelegate,
- continuationFunction, scheduler, cancellationToken, continuationOptions);
+ continuationFunction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
else
{
@@ -2063,7 +2067,7 @@ namespace System.Threading.Tasks
return starter.ContinueWith<TResult>(
// Use a cached delegate
GenericDelegateCache<TAntecedentResult, TResult>.CWAnyActionDelegate,
- continuationAction, scheduler, cancellationToken, continuationOptions);
+ continuationAction, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
}
}
@@ -2074,41 +2078,45 @@ namespace System.Threading.Tasks
internal static class GenericDelegateCache<TAntecedentResult, TResult>
{
// ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(non-null continuationFunction)
- internal static Func<Task<Task>, object, TResult> CWAnyFuncDelegate =
- (Task<Task> wrappedWinner, object state) =>
+ internal static Func<Task<Task>, object?, TResult> CWAnyFuncDelegate =
+ (Task<Task> wrappedWinner, object? state) =>
{
+ Debug.Assert(state is Func<Task<TAntecedentResult>, TResult>);
var func = (Func<Task<TAntecedentResult>, TResult>)state;
var arg = (Task<TAntecedentResult>)wrappedWinner.Result;
return func(arg);
};
// ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(non-null continuationAction)
- internal static Func<Task<Task>, object, TResult> CWAnyActionDelegate =
- (Task<Task> wrappedWinner, object state) =>
+ internal static Func<Task<Task>, object?, TResult> CWAnyActionDelegate =
+ (Task<Task> wrappedWinner, object? state) =>
{
+ Debug.Assert(state is Action<Task<TAntecedentResult>>);
var action = (Action<Task<TAntecedentResult>>)state;
var arg = (Task<TAntecedentResult>)wrappedWinner.Result;
action(arg);
- return default;
+ return default!; // TODO-NULLABLE-GENERIC
};
// ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(non-null continuationFunction)
- internal static Func<Task<Task<TAntecedentResult>[]>, object, TResult> CWAllFuncDelegate =
- (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object state) =>
+ internal static Func<Task<Task<TAntecedentResult>[]>, object?, TResult> CWAllFuncDelegate =
+ (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object? state) =>
{
wrappedAntecedents.NotifyDebuggerOfWaitCompletionIfNecessary();
+ Debug.Assert(state is Func<Task<TAntecedentResult>>);
var func = (Func<Task<TAntecedentResult>[], TResult>)state;
return func(wrappedAntecedents.Result);
};
// ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(non-null continuationAction)
- internal static Func<Task<Task<TAntecedentResult>[]>, object, TResult> CWAllActionDelegate =
- (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object state) =>
+ internal static Func<Task<Task<TAntecedentResult>[]>, object?, TResult> CWAllActionDelegate =
+ (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object? state) =>
{
wrappedAntecedents.NotifyDebuggerOfWaitCompletionIfNecessary();
+ Debug.Assert(state is Action<Task<TAntecedentResult>[]>);
var action = (Action<Task<TAntecedentResult>[]>)state;
action(wrappedAntecedents.Result);
- return default;
+ return default!; // TODO-NULLABLE-GENERIC
};
}
}