summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStephen Toub <stoub@microsoft.com>2019-04-03 21:00:16 -0400
committerGitHub <noreply@github.com>2019-04-03 21:00:16 -0400
commitb9b80640f5158bd9152e354f4918cc42cd69fe1a (patch)
treed2e82eac13e76c3b8366d9f2bbd1f6115fd1ad42 /src
parentcdcca0380f3b236c80bebd84acbcee84d76ea6cf (diff)
downloadcoreclr-b9b80640f5158bd9152e354f4918cc42cd69fe1a.tar.gz
coreclr-b9b80640f5158bd9152e354f4918cc42cd69fe1a.tar.bz2
coreclr-b9b80640f5158bd9152e354f4918cc42cd69fe1a.zip
Nullable: System.Threading.Tasks (#23691)
* Nullable: System.Threading.Tasks * Address PR feedback
Diffstat (limited to 'src')
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IAsyncResult.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/CancellationTokenSource.cs5
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracer.Noop.cs1
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracerConstants.cs1
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs35
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/Future.cs85
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/FutureFactory.cs226
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/ProducerConsumerQueues.cs13
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/IValueTaskSource.cs5
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/ManualResetValueTaskSourceCore.cs29
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs365
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs15
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs13
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs88
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExceptionHolder.cs11
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExtensions.cs1
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskFactory.cs126
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskScheduler.cs53
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskSchedulerException.cs9
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskToApm.cs13
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/ThreadPoolTaskScheduler.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TplEventSource.cs1
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs59
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Timer.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Delegate.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/MulticastDelegate.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Tasks/AsyncCausalityTracer.cs8
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs4
33 files changed, 616 insertions, 590 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs
index 6a6764a727..bbb07a7535 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs
@@ -16,7 +16,7 @@ namespace System.Globalization
public partial class CompareInfo
{
[NonSerialized]
- private Interop.Globalization.SafeSortHandle _sortHandle = null!;
+ private Interop.Globalization.SafeSortHandle _sortHandle = null!; // initialized in helper called by ctors
[NonSerialized]
private bool _isAsciiEqualityOrdinal;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
index 12f8ce2bc7..7e1e66857f 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
@@ -56,7 +56,7 @@ namespace System.Globalization
private const int undef = -1;
// Override flag
- private string _sRealName = null!; // Name you passed in (ie: en-US, en, or de-DE_phoneb)
+ private string _sRealName = null!; // Name you passed in (ie: en-US, en, or de-DE_phoneb). Initialized by helper called during initialization.
private string? _sWindowsName; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in))
// Identity
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
index 4ff055442e..78c97903ce 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
@@ -88,7 +88,7 @@ namespace System.Globalization
private const string sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
private const string universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'";
- private Calendar calendar = null!;
+ private Calendar calendar = null!; // initialized in helper called by ctors
private int firstDayOfWeek = -1;
private int calendarWeekRule = -1;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
index b638b2a00a..30471095f0 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
@@ -16,7 +16,7 @@ namespace System.Globalization
public class RegionInfo
{
// Name of this region (ie: es-US): serialized, the field used for deserialization
- private string _name = null!;
+ private string _name;
// The CultureData instance that we are going to read data from.
private readonly CultureData _cultureData;
@@ -47,7 +47,7 @@ namespace System.Globalization
throw new ArgumentException(SR.Format(SR.Argument_InvalidNeutralRegionName, name), nameof(name));
}
- SetName(name);
+ _name = _cultureData.RegionName;
}
public RegionInfo(int culture)
@@ -86,12 +86,6 @@ namespace System.Globalization
_name = _cultureData.RegionName;
}
- private void SetName(string name)
- {
- // Use the name of the region we found
- _name = _cultureData.RegionName;
- }
-
/// <summary>
/// This instance provides methods based on the current user settings.
/// These settings are volatile and may change over the lifetime of the
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
index ef2efb9c98..fe5db920ef 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
@@ -14,7 +14,7 @@ namespace System.Globalization
/// </summary>
public class StringInfo
{
- private string _str = null!;
+ private string _str = null!; // initialized in helper called by ctors
private int[]? _indexes;
diff --git a/src/System.Private.CoreLib/shared/System/IAsyncResult.cs b/src/System.Private.CoreLib/shared/System/IAsyncResult.cs
index 56ebcdb2f5..8d7b32327e 100644
--- a/src/System.Private.CoreLib/shared/System/IAsyncResult.cs
+++ b/src/System.Private.CoreLib/shared/System/IAsyncResult.cs
@@ -11,7 +11,7 @@
**
===========================================================*/
-using System;
+#nullable enable
using System.Threading;
namespace System
@@ -23,7 +23,7 @@ namespace System
WaitHandle AsyncWaitHandle { get; }
- object AsyncState { get; }
+ object? AsyncState { get; }
bool CompletedSynchronously { get; }
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/CancellationTokenSource.cs b/src/System.Private.CoreLib/shared/System/Threading/CancellationTokenSource.cs
index 9bbd5a74ec..4d01cd09ff 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/CancellationTokenSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/CancellationTokenSource.cs
@@ -133,10 +133,10 @@ namespace System.Threading
// 2. if IsCancellationRequested = false, then NotifyCancellation will see that the event exists, and will call Set().
if (IsCancellationRequested)
{
- _kernelEvent!.Set(); // TODO-NULLABLE: The ! shouldn't be necessary due to CompareExchange initialization above.
+ _kernelEvent!.Set(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
}
- return _kernelEvent!; // TODO-NULLABLE: The ! shouldn't be necessary due to CompareExchange initialization above.
+ return _kernelEvent!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
}
}
@@ -823,6 +823,7 @@ namespace System.Threading
// this work with a callback mechanism will add additional cost to other more common cases.
return new ValueTask(Task.Factory.StartNew(s =>
{
+ Debug.Assert(s is Tuple<CancellationTokenSource, long>);
var state = (Tuple<CancellationTokenSource, long>)s;
state.Item1.WaitForCallbackToComplete(state.Item2);
}, Tuple.Create(this, id), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default));
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracer.Noop.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracer.Noop.cs
index b00d5d6756..927b8fa1e4 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracer.Noop.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracer.Noop.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
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracerConstants.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracerConstants.cs
index 3677051f05..7e710677ce 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracerConstants.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/AsyncCausalityTracerConstants.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
namespace System.Threading.Tasks
{
internal enum AsyncCausalityStatus
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
index df7c9342f3..155b00a2f4 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
@@ -14,6 +14,7 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+#nullable enable
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
@@ -51,9 +52,9 @@ namespace System.Threading.Tasks
private int m_processingCount;
/// <summary>Completion state for a task representing the completion of this pair.</summary>
/// <remarks>Lazily-initialized only if the scheduler pair is shutting down or if the Completion is requested.</remarks>
- private CompletionState m_completionState;
+ private CompletionState? m_completionState;
/// <summary>Lazily-initialized work item for processing when targeting the default scheduler.</summary>
- private SchedulerWorkItem m_threadPoolWorkItem;
+ private SchedulerWorkItem? m_threadPoolWorkItem;
/// <summary>A constant value used to signal unlimited processing.</summary>
private const int UNLIMITED_PROCESSING = -1;
@@ -152,7 +153,7 @@ namespace System.Threading.Tasks
private CompletionState EnsureCompletionStateInitialized()
{
// ValueLock not needed, but it's ok if it's held
- return LazyInitializer.EnsureInitialized(ref m_completionState, () => new CompletionState());
+ return LazyInitializer.EnsureInitialized<CompletionState>(ref m_completionState!, () => new CompletionState()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
}
/// <summary>Gets whether completion has been requested.</summary>
@@ -211,10 +212,11 @@ namespace System.Threading.Tasks
cs.m_completionQueued = true;
ThreadPool.QueueUserWorkItem(state =>
{
+ Debug.Assert(state is ConcurrentExclusiveSchedulerPair);
var localThis = (ConcurrentExclusiveSchedulerPair)state;
- Debug.Assert(!localThis.m_completionState.IsCompleted, "Completion should only happen once.");
+ Debug.Assert(!localThis.m_completionState!.IsCompleted, "Completion should only happen once.");
- List<Exception> exceptions = localThis.m_completionState.m_exceptions;
+ List<Exception>? exceptions = localThis.m_completionState.m_exceptions;
bool success = (exceptions != null && exceptions.Count > 0) ?
localThis.m_completionState.TrySetException(exceptions) :
localThis.m_completionState.TrySetResult();
@@ -229,7 +231,7 @@ namespace System.Threading.Tasks
/// <param name="faultedTask">The faulted worker task that's initiating the shutdown.</param>
private void FaultWithTask(Task faultedTask)
{
- Debug.Assert(faultedTask != null && faultedTask.IsFaulted && faultedTask.Exception.InnerExceptions.Count > 0,
+ Debug.Assert(faultedTask != null && faultedTask.IsFaulted && faultedTask.Exception!.InnerExceptions.Count > 0,
"Needs a task in the faulted state and thus with exceptions.");
ContractAssertMonitorStatus(ValueLock, held: true);
@@ -287,7 +289,7 @@ namespace System.Threading.Tasks
// If there's no processing currently happening but there are waiting exclusive tasks,
// let's start processing those exclusive tasks.
- Task processingTask = null;
+ Task? processingTask = null;
if (m_processingCount == 0 && exclusiveTasksAreWaiting)
{
// Launch exclusive task processing
@@ -296,17 +298,17 @@ namespace System.Threading.Tasks
{
try
{
- processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair).ProcessExclusiveTasks(), this,
+ processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessExclusiveTasks(), this, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
default, GetCreationOptionsForTask(fairly));
processingTask.Start(m_underlyingTaskScheduler);
// When we call Start, if the underlying scheduler throws in QueueTask, TPL will fault the task and rethrow
// the exception. To deal with that, we need a reference to the task object, so that we can observe its exception.
// Hence, we separate creation and starting, so that we can store a reference to the task before we attempt QueueTask.
}
- catch
+ catch (Exception e)
{
m_processingCount = 0;
- FaultWithTask(processingTask);
+ FaultWithTask(processingTask ?? Task.FromException(e));
}
}
}
@@ -326,14 +328,14 @@ namespace System.Threading.Tasks
{
try
{
- processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair).ProcessConcurrentTasks(), this,
+ processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair!).ProcessConcurrentTasks(), this, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
default, GetCreationOptionsForTask(fairly));
processingTask.Start(m_underlyingTaskScheduler); // See above logic for why we use new + Start rather than StartNew
}
- catch
+ catch (Exception e)
{
--m_processingCount;
- FaultWithTask(processingTask);
+ FaultWithTask(processingTask ?? Task.FromException(e));
}
}
}
@@ -485,7 +487,7 @@ namespace System.Threading.Tasks
/// <summary>Whether completion processing has been queued.</summary>
internal bool m_completionQueued;
/// <summary>Unrecoverable exceptions incurred while processing.</summary>
- internal List<Exception> m_exceptions;
+ internal List<Exception>? m_exceptions;
}
/// <summary>Reusable immutable work item that can be scheduled to the thread pool to run processing.</summary>
@@ -516,7 +518,7 @@ namespace System.Threading.Tasks
private sealed class ConcurrentExclusiveTaskScheduler : TaskScheduler
{
/// <summary>Cached delegate for invoking TryExecuteTaskShim.</summary>
- private static readonly Func<object, bool> s_tryExecuteTaskShim = new Func<object, bool>(TryExecuteTaskShim);
+ private static readonly Func<object?, bool> s_tryExecuteTaskShim = new Func<object?, bool>(TryExecuteTaskShim);
/// <summary>The parent pair.</summary>
private readonly ConcurrentExclusiveSchedulerPair m_pair;
/// <summary>The maximum concurrency level for the scheduler.</summary>
@@ -666,8 +668,9 @@ namespace System.Threading.Tasks
/// This method is separated out not because of performance reasons but so that
/// the SecuritySafeCritical attribute may be employed.
/// </remarks>
- private static bool TryExecuteTaskShim(object state)
+ private static bool TryExecuteTaskShim(object? state)
{
+ Debug.Assert(state is Tuple<ConcurrentExclusiveTaskScheduler, Task>);
var tuple = (Tuple<ConcurrentExclusiveTaskScheduler, Task>)state;
return tuple.Item1.TryExecuteTask(tuple.Item2);
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Future.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Future.cs
index 0b93ee85df..9e562e3c46 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Future.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Future.cs
@@ -10,6 +10,7 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+#nullable enable
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
@@ -60,7 +61,7 @@ namespace System.Threading.Tasks
[DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}, Result = {DebuggerDisplayResultDescription}")]
public class Task<TResult> : Task
{
- internal TResult m_result; // The value itself, if set.
+ internal TResult m_result = default!; // The value itself, if set. // TODO-NULLABLE-GENERIC
private static readonly TaskFactory<TResult> s_Factory = new TaskFactory<TResult>();
@@ -75,14 +76,14 @@ namespace System.Threading.Tasks
internal static readonly Func<Task<Task>, Task<TResult>> Value = completed => (Task<TResult>)completed.Result;
}
- // Construct a promise-style task without any options.
+ // Construct a promise-style task without any options.
internal Task() :
base()
{
}
// Construct a promise-style task with state and options.
- internal Task(object state, TaskCreationOptions options) :
+ internal Task(object? state, TaskCreationOptions options) :
base(state, options, promiseStyle: true)
{
}
@@ -209,7 +210,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentException">
/// The <paramref name="function"/> argument is null.
/// </exception>
- public Task(Func<object, TResult> function, object state)
+ public Task(Func<object?, TResult> function, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
: this(function, state, null, default,
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
@@ -230,7 +231,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task(Func<object, TResult> function, object state, CancellationToken cancellationToken)
+ public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
: this(function, state, null, cancellationToken,
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
@@ -255,7 +256,7 @@ namespace System.Threading.Tasks
/// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
/// </exception>
- public Task(Func<object, TResult> function, object state, TaskCreationOptions creationOptions)
+ public Task(Func<object?, TResult> function, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
: this(function, state, Task.InternalCurrentIfAttached(creationOptions), default,
creationOptions, InternalTaskOptions.None, null)
{
@@ -285,7 +286,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task(Func<object, TResult> function, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
+ public Task(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
: this(function, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken,
creationOptions, InternalTaskOptions.None, null)
{
@@ -300,8 +301,8 @@ namespace System.Threading.Tasks
/// <param name="cancellationToken">The CancellationToken for the task.</param>
/// <param name="creationOptions">Options to control the future's behavior.</param>
/// <param name="internalOptions">Internal options to control the future's behavior.</param>
- internal Task(Func<TResult> valueSelector, Task parent, CancellationToken cancellationToken,
- TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
+ internal Task(Func<TResult> valueSelector, Task? parent, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler? scheduler) :
base(valueSelector, null, parent, cancellationToken, creationOptions, internalOptions, scheduler)
{
}
@@ -316,15 +317,15 @@ namespace System.Threading.Tasks
/// <param name="scheduler">The task scheduler which will be used to execute the future.</param>
/// <param name="creationOptions">Options to control the future's behavior.</param>
/// <param name="internalOptions">Internal options to control the future's behavior.</param>
- internal Task(Delegate valueSelector, object state, Task parent, CancellationToken cancellationToken,
- TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
+ internal Task(Delegate valueSelector, object? state, Task? parent, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler? scheduler) :
base(valueSelector, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
{
}
// Internal method used by TaskFactory<TResult>.StartNew() methods
- internal static Task<TResult> StartNew(Task parent, Func<TResult> function, CancellationToken cancellationToken,
+ internal static Task<TResult> StartNew(Task? parent, Func<TResult> function, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
{
if (function == null)
@@ -337,14 +338,14 @@ namespace System.Threading.Tasks
}
// Create and schedule the future.
- Task<TResult> f = new Task<TResult>(function, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
+ Task<TResult> f = new Task<TResult>(function!, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
f.ScheduleAndStart(false);
return f;
}
// Internal method used by TaskFactory<TResult>.StartNew() methods
- internal static Task<TResult> StartNew(Task parent, Func<object, TResult> function, object state, CancellationToken cancellationToken,
+ internal static Task<TResult> StartNew(Task? parent, Func<object?, TResult> function, object? state, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
{
if (function == null)
@@ -357,7 +358,7 @@ namespace System.Threading.Tasks
}
// Create and schedule the future.
- Task<TResult> f = new Task<TResult>(function, state, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
+ Task<TResult> f = new Task<TResult>(function!, state, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
f.ScheduleAndStart(false);
return f;
@@ -377,8 +378,7 @@ namespace System.Threading.Tasks
{
get
{
- Delegate d = m_action;
- return d != null ? d.Method.ToString() : "{null}";
+ return m_action?.Method.ToString() ?? "{null}";
}
}
@@ -408,7 +408,7 @@ namespace System.Threading.Tasks
// and which can be summarized more concisely with the following snippet from
// FinishStageTwo, omitting everything that doesn't pertain to TrySetResult.
Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_RAN_TO_COMPLETION);
- ContingentProperties props = m_contingentProperties;
+ ContingentProperties? props = m_contingentProperties;
if (props != null)
{
NotifyParentIfPotentiallyAttachedTask();
@@ -518,7 +518,7 @@ namespace System.Threading.Tasks
return;
}
- if (m_action is Func<object, TResult> funcWithState)
+ if (m_action is Func<object?, TResult> funcWithState)
{
m_result = funcWithState(m_stateObject);
return;
@@ -726,13 +726,13 @@ namespace System.Threading.Tasks
out internalOptions);
Task continuationTask = new ContinuationTaskFromResultTask<TResult>(
- this, continuationAction, null,
+ this, continuationAction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
- ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+ ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
return continuationTask;
}
@@ -757,7 +757,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
- public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state)
+ public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default, TaskContinuationOptions.None);
}
@@ -784,7 +784,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, CancellationToken cancellationToken)
+ public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
@@ -813,7 +813,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, TaskScheduler scheduler)
+ public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
return ContinueWith(continuationAction, state, scheduler, default, TaskContinuationOptions.None);
}
@@ -847,7 +847,7 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
+ public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskContinuationOptions continuationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default, continuationOptions);
}
@@ -891,14 +891,14 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, CancellationToken cancellationToken,
+ public Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, only with a stack mark.
- internal Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, TaskScheduler scheduler, CancellationToken cancellationToken,
+ internal Task ContinueWith(Action<Task<TResult>, object?> continuationAction, object? state, TaskScheduler scheduler, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
TaskContinuationOptions continuationOptions)
{
if (continuationAction == null)
@@ -919,13 +919,13 @@ namespace System.Threading.Tasks
out internalOptions);
Task continuationTask = new ContinuationTaskFromResultTask<TResult>(
- this, continuationAction, state,
+ this, continuationAction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
- ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+ ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
return continuationTask;
}
@@ -1135,13 +1135,13 @@ namespace System.Threading.Tasks
out internalOptions);
Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult, TNewResult>(
- this, continuationFunction, null,
+ this, continuationFunction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
- ContinueWithCore(continuationFuture, scheduler, cancellationToken, continuationOptions);
+ ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
return continuationFuture;
}
@@ -1169,7 +1169,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
- public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state)
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state)
{
return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default, TaskContinuationOptions.None);
}
@@ -1199,7 +1199,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state,
CancellationToken cancellationToken)
{
return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
@@ -1231,7 +1231,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state,
TaskScheduler scheduler)
{
return ContinueWith<TNewResult>(continuationFunction, state, scheduler, default, TaskContinuationOptions.None);
@@ -1275,7 +1275,7 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state,
TaskContinuationOptions continuationOptions)
{
return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default, continuationOptions);
@@ -1330,14 +1330,14 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith<TNewResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, just with a stack mark.
- internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
+ internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object?, TNewResult> continuationFunction, object? state,
TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null)
@@ -1358,13 +1358,13 @@ namespace System.Threading.Tasks
out internalOptions);
Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult, TNewResult>(
- this, continuationFunction, state,
+ this, continuationFunction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
- ContinueWithCore(continuationFuture, scheduler, cancellationToken, continuationOptions);
+ ContinueWithCore(continuationFuture, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
return continuationFuture;
}
@@ -1381,13 +1381,14 @@ namespace System.Threading.Tasks
public SystemThreadingTasks_FutureDebugView(Task<TResult> task)
{
+ Debug.Assert(task != null);
m_task = task;
}
- public TResult Result { get { return m_task.Status == TaskStatus.RanToCompletion ? m_task.Result : default; } }
- public object AsyncState { get { return m_task.AsyncState; } }
+ public TResult Result { get { return m_task.Status == TaskStatus.RanToCompletion ? m_task.Result : default!; } } // TODO-NULLABLE-GENERIC
+ public object? AsyncState { get { return m_task.AsyncState; } }
public TaskCreationOptions CreationOptions { get { return m_task.CreationOptions; } }
- public Exception Exception { get { return m_task.Exception; } }
+ public Exception? Exception { get { return m_task.Exception; } }
public int Id { get { return m_task.Id; } }
public bool CancellationPending { get { return (m_task.Status == TaskStatus.WaitingToRun) && m_task.CancellationToken.IsCancellationRequested; } }
public TaskStatus Status { get { return m_task.Status; } }
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
};
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ProducerConsumerQueues.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ProducerConsumerQueues.cs
index 1880288c51..21214e85a8 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ProducerConsumerQueues.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ProducerConsumerQueues.cs
@@ -21,6 +21,7 @@
// ************</IMPORTANT NOTE>*************
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+#nullable enable
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -204,7 +205,7 @@ namespace System.Threading.Tasks
if (first != segment.m_state.m_lastCopy)
{
result = array[first];
- array[first] = default; // Clear the slot to release the element
+ array[first] = default!; // Clear the slot to release the element // TODO-NULLABLE-GENERIC
segment.m_state.m_first = (first + 1) & (array.Length - 1);
return true;
}
@@ -239,12 +240,12 @@ namespace System.Threading.Tasks
if (first == segment.m_state.m_last)
{
- result = default;
+ result = default!; // TODO-NULLABLE-GENERIC
return false;
}
result = array[first];
- array[first] = default; // Clear the slot to release the element
+ array[first] = default!; // Clear the slot to release the element // TODO-NULLABLE-GENERIC
segment.m_state.m_first = (first + 1) & (segment.m_array.Length - 1);
segment.m_state.m_lastCopy = segment.m_state.m_last; // Refresh m_lastCopy to ensure that m_first has not passed m_lastCopy
@@ -269,7 +270,7 @@ namespace System.Threading.Tasks
/// <remarks>WARNING: This should only be used for debugging purposes. It is not safe to be used concurrently.</remarks>
public IEnumerator<T> GetEnumerator()
{
- for (Segment segment = m_head; segment != null; segment = segment.m_next)
+ for (Segment? segment = m_head; segment != null; segment = segment.m_next)
{
for (int pt = segment.m_state.m_first;
pt != segment.m_state.m_last;
@@ -290,7 +291,7 @@ namespace System.Threading.Tasks
get
{
int count = 0;
- for (Segment segment = m_head; segment != null; segment = segment.m_next)
+ for (Segment? segment = m_head; segment != null; segment = segment.m_next)
{
int arraySize = segment.m_array.Length;
int first, last;
@@ -311,7 +312,7 @@ namespace System.Threading.Tasks
private sealed class Segment
{
/// <summary>The next segment in the linked list of segments.</summary>
- internal Segment m_next;
+ internal Segment? m_next;
/// <summary>The data stored in this segment.</summary>
internal readonly T[] m_array;
/// <summary>Details about the segment.</summary>
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/IValueTaskSource.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/IValueTaskSource.cs
index e411146a1d..6181ab2bf0 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/IValueTaskSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/IValueTaskSource.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
namespace System.Threading.Tasks.Sources
{
/// <summary>
@@ -53,7 +54,7 @@ namespace System.Threading.Tasks.Sources
/// <param name="state">The state object to pass to <paramref name="continuation"/> when it's invoked.</param>
/// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param>
/// <param name="flags">The flags describing the behavior of the continuation.</param>
- void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags);
+ void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
/// <summary>Gets the result of the <see cref="IValueTaskSource"/>.</summary>
/// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param>
@@ -73,7 +74,7 @@ namespace System.Threading.Tasks.Sources
/// <param name="state">The state object to pass to <paramref name="continuation"/> when it's invoked.</param>
/// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param>
/// <param name="flags">The flags describing the behavior of the continuation.</param>
- void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags);
+ void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
/// <summary>Gets the result of the <see cref="IValueTaskSource{TResult}"/>.</summary>
/// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param>
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/ManualResetValueTaskSourceCore.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/ManualResetValueTaskSourceCore.cs
index 797ed6ed8a..967cbbeadf 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/ManualResetValueTaskSourceCore.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Sources/ManualResetValueTaskSourceCore.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;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
@@ -18,22 +19,22 @@ namespace System.Threading.Tasks.Sources
/// or <see cref="ManualResetValueTaskSourceCoreShared.s_sentinel"/> if the operation completed before a callback was supplied,
/// or null if a callback hasn't yet been provided and the operation hasn't yet completed.
/// </summary>
- private Action<object> _continuation;
+ private Action<object?>? _continuation;
/// <summary>State to pass to <see cref="_continuation"/>.</summary>
- private object _continuationState;
+ private object? _continuationState;
/// <summary><see cref="ExecutionContext"/> to flow to the callback, or null if no flowing is required.</summary>
- private ExecutionContext _executionContext;
+ private ExecutionContext? _executionContext;
/// <summary>
/// A "captured" <see cref="SynchronizationContext"/> or <see cref="TaskScheduler"/> with which to invoke the callback,
/// or null if no special context is required.
/// </summary>
- private object _capturedContext;
+ private object? _capturedContext;
/// <summary>Whether the current operation has completed.</summary>
private bool _completed;
/// <summary>The result with which the operation succeeded, or the default value if it hasn't yet completed or failed.</summary>
private TResult _result;
/// <summary>The exception with which the operation failed, or null if it hasn't yet completed or completed successfully.</summary>
- private ExceptionDispatchInfo _error;
+ private ExceptionDispatchInfo? _error;
/// <summary>The current version of this value, used to help prevent misuse.</summary>
private short _version;
@@ -47,7 +48,7 @@ namespace System.Threading.Tasks.Sources
// Reset/update state for the next use/await of this instance.
_version++;
_completed = false;
- _result = default;
+ _result = default!; // TODO-NULLABLE-GENERIC
_error = null;
_executionContext = null;
_capturedContext = null;
@@ -106,7 +107,7 @@ namespace System.Threading.Tasks.Sources
/// <param name="state">The state object to pass to <paramref name="continuation"/> when it's invoked.</param>
/// <param name="token">Opaque value that was provided to the <see cref="ValueTask"/>'s constructor.</param>
/// <param name="flags">The flags describing the behavior of the continuation.</param>
- public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
+ public void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
if (continuation == null)
{
@@ -121,7 +122,7 @@ namespace System.Threading.Tasks.Sources
if ((flags & ValueTaskSourceOnCompletedFlags.UseSchedulingContext) != 0)
{
- SynchronizationContext sc = SynchronizationContext.Current;
+ SynchronizationContext? sc = SynchronizationContext.Current;
if (sc != null && sc.GetType() != typeof(SynchronizationContext))
{
_capturedContext = sc;
@@ -144,7 +145,7 @@ namespace System.Threading.Tasks.Sources
// To minimize the chances of that, we check preemptively whether _continuation
// is already set to something other than the completion sentinel.
- object oldContinuation = _continuation;
+ object? oldContinuation = _continuation;
if (oldContinuation == null)
{
_continuationState = state;
@@ -175,7 +176,7 @@ namespace System.Threading.Tasks.Sources
case SynchronizationContext sc:
sc.Post(s =>
{
- var tuple = (Tuple<Action<object>, object>)s;
+ var tuple = (Tuple<Action<object?>, object?>)s!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
tuple.Item1(tuple.Item2);
}, Tuple.Create(continuation, state));
break;
@@ -229,6 +230,8 @@ namespace System.Threading.Tasks.Sources
/// </summary>
private void InvokeContinuation()
{
+ Debug.Assert(_continuation != null);
+
switch (_capturedContext)
{
case null:
@@ -252,7 +255,7 @@ namespace System.Threading.Tasks.Sources
case SynchronizationContext sc:
sc.Post(s =>
{
- var state = (Tuple<Action<object>, object>)s;
+ var state = (Tuple<Action<object?>, object?>)s!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
state.Item1(state.Item2);
}, Tuple.Create(_continuation, _continuationState));
break;
@@ -266,8 +269,8 @@ namespace System.Threading.Tasks.Sources
internal static class ManualResetValueTaskSourceCoreShared // separated out of generic to avoid unnecessary duplication
{
- internal static readonly Action<object> s_sentinel = CompletionSentinel;
- private static void CompletionSentinel(object _) // named method to aid debugging
+ internal static readonly Action<object?> s_sentinel = CompletionSentinel;
+ private static void CompletionSentinel(object? _) // named method to aid debugging
{
Debug.Fail("The sentinel delegate should never be invoked.");
ThrowHelper.ThrowInvalidOperationException();
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs
index 5d893c5cee..a8aac04936 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs
@@ -10,6 +10,7 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+#nullable enable
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
@@ -130,13 +131,13 @@ namespace System.Threading.Tasks
public class Task : IAsyncResult, IDisposable
{
[ThreadStatic]
- internal static Task t_currentTask; // The currently executing task.
+ internal static Task? t_currentTask; // The currently executing task.
internal static int s_taskIdCounter; //static counter used to generate unique task IDs
private volatile int m_taskId; // this task's unique ID. initialized only if it is ever requested
- internal Delegate m_action; // The body of the task. Might be Action<object>, Action<TState> or Action. Or possibly a Func.
+ internal Delegate? m_action; // The body of the task. Might be Action<object>, Action<TState> or Action. Or possibly a Func.
// If m_action is set to null it will indicate that we operate in the
// "externally triggered completion" mode, which is exclusively meant
// for the signalling Task<TResult> (aka. promise). In this mode,
@@ -145,12 +146,12 @@ namespace System.Threading.Tasks
// But the event would now be signalled if Cancel() is called
- internal object m_stateObject; // A state object that can be optionally supplied, passed to action.
- internal TaskScheduler m_taskScheduler; // The task scheduler this task runs under.
+ internal object? m_stateObject; // A state object that can be optionally supplied, passed to action.
+ internal TaskScheduler? m_taskScheduler; // The task scheduler this task runs under.
internal volatile int m_stateFlags; // SOS DumpAsync command depends on this name
- private Task ParentForDebugger => m_contingentProperties?.m_parent; // Private property used by a debugger to access this Task's parent
+ private Task? ParentForDebugger => m_contingentProperties?.m_parent; // Private property used by a debugger to access this Task's parent
private int StateFlagsForDebugger => m_stateFlags; // Private property used by a debugger to access this Task's state flags
// State constants for m_stateFlags;
@@ -188,7 +189,7 @@ namespace System.Threading.Tasks
// Can be null, a single continuation, a list of continuations, or s_taskCompletionSentinel,
// in that order. The logic arround this object assumes it will never regress to a previous state.
- private volatile object m_continuationObject = null; // SOS DumpAsync command depends on this name
+ private volatile object? m_continuationObject = null; // SOS DumpAsync command depends on this name
// m_continuationObject is set to this when the task completes.
private static readonly object s_taskCompletionSentinel = new object();
@@ -199,7 +200,7 @@ namespace System.Threading.Tasks
// This dictonary relates the task id, from an operation id located in the Async Causality log to the actual
// task. This is to be used by the debugger ONLY. Task in this dictionary represent current active tasks.
- private static Dictionary<int, Task> s_currentActiveTasks;
+ private static Dictionary<int, Task>? s_currentActiveTasks;
// These methods are a way to access the dictionary both from this class and for other classes that also
// activate dummy tasks. Specifically the AsyncTaskMethodBuilder and AsyncTaskMethodBuilder<>
@@ -210,9 +211,9 @@ namespace System.Threading.Tasks
LazyInitializer.EnsureInitialized(ref s_currentActiveTasks, () => new Dictionary<int, Task>());
int taskId = task.Id;
- lock (s_currentActiveTasks)
+ lock (s_currentActiveTasks!) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
- s_currentActiveTasks[taskId] = task;
+ s_currentActiveTasks![taskId] = task; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
}
//always return true to keep signature as bool for backwards compatibility
return true;
@@ -238,17 +239,17 @@ namespace System.Threading.Tasks
{
// Additional context
- internal ExecutionContext m_capturedContext; // The execution context to run the task within, if any. Only set from non-concurrent contexts.
+ internal ExecutionContext? m_capturedContext; // The execution context to run the task within, if any. Only set from non-concurrent contexts.
// Completion fields (exceptions and event)
- internal volatile ManualResetEventSlim m_completionEvent; // Lazily created if waiting is required.
- internal volatile TaskExceptionHolder m_exceptionsHolder; // Tracks exceptions, if any have occurred
+ internal volatile ManualResetEventSlim? m_completionEvent; // Lazily created if waiting is required.
+ internal volatile TaskExceptionHolder? m_exceptionsHolder; // Tracks exceptions, if any have occurred
// Cancellation fields (token, registration, and internally requested)
internal CancellationToken m_cancellationToken; // Task's cancellation token, if it has one
- internal Shared<CancellationTokenRegistration> m_cancellationRegistration; // Task's registration with the cancellation token
+ internal Shared<CancellationTokenRegistration>? m_cancellationRegistration; // Task's registration with the cancellation token
internal volatile int m_internalCancellationRequested; // Its own field because multiple threads legally try to set it.
// Parenting fields
@@ -260,9 +261,9 @@ namespace System.Threading.Tasks
internal volatile int m_completionCountdown = 1;
// A list of child tasks that threw an exception (TCEs don't count),
// but haven't yet been waited on by the parent, lazily initialized.
- internal volatile List<Task> m_exceptionalChildren;
+ internal volatile List<Task>? m_exceptionalChildren;
// A task's parent, or null if parent-less. Only set during Task construction.
- internal Task m_parent;
+ internal Task? m_parent;
/// <summary>
/// Sets the internal completion event.
@@ -295,7 +296,7 @@ namespace System.Threading.Tasks
// This field will only be instantiated to some non-null value if any ContingentProperties need to be set.
// This will be a ContingentProperties instance or a type derived from it
- internal ContingentProperties m_contingentProperties;
+ internal ContingentProperties? m_contingentProperties;
// Special internal constructor to create an already-completed task.
// if canceled==true, create a Canceled task, or else create a RanToCompletion task.
@@ -325,7 +326,7 @@ namespace System.Threading.Tasks
// Special constructor for use with promise-style tasks.
// Added promiseStyle parameter as an aid to the compiler to distinguish between (state,TCO) and
// (action,TCO). It should always be true.
- internal Task(object state, TaskCreationOptions creationOptions, bool promiseStyle)
+ internal Task(object? state, TaskCreationOptions creationOptions, bool promiseStyle)
{
Debug.Assert(promiseStyle, "Promise CTOR: promiseStyle was false");
@@ -339,7 +340,7 @@ namespace System.Threading.Tasks
// Only set a parent if AttachedToParent is specified.
if ((creationOptions & TaskCreationOptions.AttachedToParent) != 0)
{
- Task parent = Task.InternalCurrent;
+ Task? parent = Task.InternalCurrent;
if (parent != null)
{
EnsureContingentPropertiesInitializedUnsafe().m_parent = parent;
@@ -427,7 +428,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="action"/> argument is null.
/// </exception>
- public Task(Action<object> action, object state)
+ public Task(Action<object?> action, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
: this(action, state, null, default, TaskCreationOptions.None, InternalTaskOptions.None, null)
{
}
@@ -444,7 +445,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task(Action<object> action, object state, CancellationToken cancellationToken)
+ public Task(Action<object?> action, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
: this(action, state, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
{
}
@@ -465,7 +466,7 @@ namespace System.Threading.Tasks
/// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
/// </exception>
- public Task(Action<object> action, object state, TaskCreationOptions creationOptions)
+ public Task(Action<object?> action, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
: this(action, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null)
{
}
@@ -490,7 +491,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
+ public Task(Action<object?> action, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
: this(action, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
{
}
@@ -505,8 +506,8 @@ namespace System.Threading.Tasks
/// <param name="scheduler">A task scheduler under which the task will run.</param>
/// <param name="creationOptions">Options to control its execution.</param>
/// <param name="internalOptions">Internal options to control its execution</param>
- internal Task(Delegate action, object state, Task parent, CancellationToken cancellationToken,
- TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
+ internal Task(Delegate action, object? state, Task? parent, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler? scheduler)
{
if (action == null)
{
@@ -537,8 +538,8 @@ namespace System.Threading.Tasks
/// <param name="cancellationToken">A CancellationToken for the Task.</param>
/// <param name="creationOptions">Options to customize behavior of Task.</param>
/// <param name="internalOptions">Internal options to customize behavior of Task.</param>
- internal void TaskConstructorCore(Delegate action, object state, CancellationToken cancellationToken,
- TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
+ internal void TaskConstructorCore(Delegate? action, object? state, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler? scheduler)
{
m_action = action;
m_stateObject = state;
@@ -580,10 +581,10 @@ namespace System.Threading.Tasks
// We can safely call the creator task's AddNewChild() method to register it,
// because at this point we are already on its thread of execution.
- ContingentProperties props = m_contingentProperties;
+ ContingentProperties? props = m_contingentProperties;
if (props != null)
{
- Task parent = props.m_parent;
+ Task? parent = props.m_parent;
if (parent != null
&& ((creationOptions & TaskCreationOptions.AttachedToParent) != 0)
&& ((parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0))
@@ -606,7 +607,7 @@ namespace System.Threading.Tasks
/// Handles everything needed for associating a CancellationToken with a task which is being constructed.
/// This method is meant to be called either from the TaskConstructorCore or from ContinueWithCore.
/// </summary>
- private void AssignCancellationToken(CancellationToken cancellationToken, Task antecedent, TaskContinuation continuation)
+ private void AssignCancellationToken(CancellationToken cancellationToken, Task? antecedent, TaskContinuation? continuation)
{
// There is no need to worry about concurrency issues here because we are in the constructor path of the task --
// there should not be any race conditions to set m_contingentProperties at this point.
@@ -634,16 +635,18 @@ namespace System.Threading.Tasks
if (antecedent == null)
{
// if no antecedent was specified, use this task's reference as the cancellation state object
- ctr = cancellationToken.UnsafeRegister(t => ((Task)t).InternalCancel(false), this);
+ ctr = cancellationToken.UnsafeRegister(t => ((Task)t!).InternalCancel(false), this); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
}
else
{
+ Debug.Assert(continuation != null);
+
// If an antecedent was specified, pack this task, its antecedent and the TaskContinuation together as a tuple
// and use it as the cancellation state object. This will be unpacked in the cancellation callback so that
// antecedent.RemoveCancellation(continuation) can be invoked.
ctr = cancellationToken.UnsafeRegister(t =>
{
- var tuple = (Tuple<Task, Task, TaskContinuation>)t;
+ var tuple = (Tuple<Task, Task, TaskContinuation>)t!;
Task targetTask = tuple.Item1;
Task antecedentTask = tuple.Item2;
@@ -662,7 +665,7 @@ namespace System.Threading.Tasks
{
// If we have an exception related to our CancellationToken, then we need to subtract ourselves
// from our parent before throwing it.
- Task parent = m_contingentProperties?.m_parent;
+ Task? parent = m_contingentProperties?.m_parent;
if ((parent != null) &&
((Options & TaskCreationOptions.AttachedToParent) != 0)
&& ((parent.Options & TaskCreationOptions.DenyChildAttach) == 0))
@@ -678,8 +681,7 @@ namespace System.Threading.Tasks
{
get
{
- Delegate d = m_action;
- return d != null ? d.Method.ToString() : "{null}";
+ return m_action?.Method.ToString() ?? "{null}";
}
}
@@ -787,7 +789,7 @@ namespace System.Threading.Tasks
/// <summary>Returns true if any of the supplied tasks require wait notification.</summary>
/// <param name="tasks">The tasks to check.</param>
/// <returns>true if any of the tasks require notification; otherwise, false.</returns>
- internal static bool AnyTaskRequiresNotifyDebuggerOfWaitCompletion(Task[] tasks)
+ internal static bool AnyTaskRequiresNotifyDebuggerOfWaitCompletion(Task?[] tasks)
{
Debug.Assert(tasks != null, "Expected non-null array of tasks");
foreach (var task in tasks)
@@ -871,8 +873,8 @@ namespace System.Threading.Tasks
{
m_stateFlags |= Task.TASK_STATE_TASKSCHEDULED_WAS_FIRED;
- Task currentTask = Task.InternalCurrent;
- Task parentTask = m_contingentProperties?.m_parent;
+ Task? currentTask = Task.InternalCurrent;
+ Task? parentTask = m_contingentProperties?.m_parent;
TplEventSource.Log.TaskScheduled(ts.Id, currentTask == null ? 0 : currentTask.Id,
this.Id, parentTask == null ? 0 : parentTask.Id, (int)this.Options);
}
@@ -1049,7 +1051,7 @@ namespace System.Threading.Tasks
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
}
- InternalRunSynchronously(scheduler, waitForCompletion: true);
+ InternalRunSynchronously(scheduler!, waitForCompletion: true); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
//
@@ -1158,7 +1160,7 @@ namespace System.Threading.Tasks
// Implicitly converts action to object and handles the meat of the StartNew() logic.
internal static Task InternalStartNew(
- Task creatingTask, Delegate action, object state, CancellationToken cancellationToken, TaskScheduler scheduler,
+ Task? creatingTask, Delegate action, object? state, CancellationToken cancellationToken, TaskScheduler scheduler,
TaskCreationOptions options, InternalTaskOptions internalOptions)
{
// Validate arguments.
@@ -1227,7 +1229,7 @@ namespace System.Threading.Tasks
{
get
{
- Task currentTask = InternalCurrent;
+ Task? currentTask = InternalCurrent;
if (currentTask != null)
return currentTask.Id;
else
@@ -1239,7 +1241,7 @@ namespace System.Threading.Tasks
/// Gets the <see cref="Task">Task</see> instance currently executing, or
/// null if none exists.
/// </summary>
- internal static Task InternalCurrent
+ internal static Task? InternalCurrent
{
get { return t_currentTask; }
}
@@ -1250,7 +1252,7 @@ namespace System.Threading.Tasks
/// </summary>
/// <param name="creationOptions">The options to check.</param>
/// <returns>The current task if there is one and if AttachToParent is in the options; otherwise, null.</returns>
- internal static Task InternalCurrentIfAttached(TaskCreationOptions creationOptions)
+ internal static Task? InternalCurrentIfAttached(TaskCreationOptions creationOptions)
{
return (creationOptions & TaskCreationOptions.AttachedToParent) != 0 ? InternalCurrent : null;
}
@@ -1267,11 +1269,11 @@ namespace System.Threading.Tasks
/// or in accesses to the <see cref="Exception"/> property. Any exceptions not observed by the time
/// the Task instance is garbage collected will be propagated on the finalizer thread.
/// </remarks>
- public AggregateException Exception
+ public AggregateException? Exception
{
get
{
- AggregateException e = null;
+ AggregateException? e = null;
// If you're faulted, retrieve the exception(s)
if (IsFaulted) e = GetExceptions(false);
@@ -1355,7 +1357,7 @@ namespace System.Threading.Tasks
/// <returns>The initialized contingent properties object.</returns>
internal ContingentProperties EnsureContingentPropertiesInitialized()
{
- return LazyInitializer.EnsureInitialized(ref m_contingentProperties, () => new ContingentProperties());
+ return LazyInitializer.EnsureInitialized(ref m_contingentProperties, () => new ContingentProperties())!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
}
/// <summary>
@@ -1460,7 +1462,7 @@ namespace System.Threading.Tasks
/// Gets the state object supplied when the <see cref="Task">Task</see> was created,
/// or null if none was supplied.
/// </summary>
- public object AsyncState
+ public object? AsyncState
{
get { return m_stateObject; }
}
@@ -1480,7 +1482,7 @@ namespace System.Threading.Tasks
/// <summary>
/// Provides access to the TaskScheduler responsible for executing this Task.
/// </summary>
- internal TaskScheduler ExecutingTaskScheduler
+ internal TaskScheduler? ExecutingTaskScheduler
{
get { return m_taskScheduler; }
}
@@ -1524,13 +1526,13 @@ namespace System.Threading.Tasks
}
}
- return contingentProps.m_completionEvent;
+ return contingentProps.m_completionEvent!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
}
}
/// <summary>
- /// The property formerly known as IsFaulted.
+ /// Whether an exception has been stored into the task.
/// </summary>
internal bool ExceptionRecorded
{
@@ -1563,7 +1565,7 @@ namespace System.Threading.Tasks
/// If the TASK_STATE_EXECUTIONCONTEXT_IS_NULL flag is set, this means ExecutionContext.Capture returned null, otherwise
/// If the captured context is the default, nothing is saved, otherwise the m_contingentProperties inflates to save the context
/// </summary>
- internal ExecutionContext CapturedContext
+ internal ExecutionContext? CapturedContext
{
get
{
@@ -1716,6 +1718,7 @@ namespace System.Threading.Tasks
if (AsyncCausalityTracer.LoggingOn && (Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0)
{
//For all other task than TaskContinuations we want to log. TaskContinuations log in their constructor
+ Debug.Assert(m_action != null, "Must have a delegate to be in ScheduleAndStart");
AsyncCausalityTracer.TraceOperationCreation(this, "Task: " + m_action.Method.Name);
}
@@ -1813,7 +1816,7 @@ namespace System.Threading.Tasks
lock (props)
{
- props.m_exceptionsHolder.Add(exceptionObject, representsCancellation);
+ props.m_exceptionsHolder!.Add(exceptionObject, representsCancellation); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
}
}
@@ -1823,7 +1826,7 @@ namespace System.Threading.Tasks
/// </summary>
/// <param name="includeTaskCanceledExceptions">Whether to include a TCE if cancelled.</param>
/// <returns>An aggregate exception, or null if no exceptions have been caught.</returns>
- private AggregateException GetExceptions(bool includeTaskCanceledExceptions)
+ private AggregateException? GetExceptions(bool includeTaskCanceledExceptions)
{
//
// WARNING: The Task/Task<TResult>/TaskCompletionSource classes
@@ -1861,7 +1864,7 @@ namespace System.Threading.Tasks
//
// We'll lazily create a TCE if the task has been canceled.
- Exception canceledException = null;
+ Exception? canceledException = null;
if (includeTaskCanceledExceptions && IsCanceled)
{
// Backcompat:
@@ -1877,7 +1880,7 @@ namespace System.Threading.Tasks
{
// There are exceptions; get the aggregate and optionally add the canceled
// exception to the aggregate (if applicable).
- Debug.Assert(m_contingentProperties != null); // ExceptionRecorded ==> m_contingentProperties != null
+ Debug.Assert(m_contingentProperties != null && m_contingentProperties.m_exceptionsHolder != null, "ExceptionRecorded should imply this");
// No need to lock around this, as other logic prevents the consumption of exceptions
// before they have been completely processed.
@@ -1898,13 +1901,13 @@ namespace System.Threading.Tasks
bool exceptionsAvailable = IsFaulted && ExceptionRecorded;
Debug.Assert(exceptionsAvailable, "Must only be used when the task has faulted with exceptions.");
return exceptionsAvailable ?
- m_contingentProperties.m_exceptionsHolder.GetExceptionDispatchInfos() :
+ m_contingentProperties!.m_exceptionsHolder!.GetExceptionDispatchInfos() :
new ReadOnlyCollection<ExceptionDispatchInfo>(new ExceptionDispatchInfo[0]);
}
/// <summary>Gets the ExceptionDispatchInfo containing the OperationCanceledException for this task.</summary>
/// <returns>The ExceptionDispatchInfo. May be null if no OCE was stored for the task.</returns>
- internal ExceptionDispatchInfo GetCancellationExceptionDispatchInfo()
+ internal ExceptionDispatchInfo? GetCancellationExceptionDispatchInfo()
{
Debug.Assert(IsCanceled, "Must only be used when the task has canceled.");
return Volatile.Read(ref m_contingentProperties)?.m_exceptionsHolder?.GetCancellationExceptionDispatchInfo(); // may be null
@@ -1917,7 +1920,7 @@ namespace System.Threading.Tasks
{
Debug.Assert(IsCompleted, "ThrowIfExceptional(): Expected IsCompleted == true");
- Exception exception = GetExceptions(includeTaskCanceledExceptions);
+ Exception? exception = GetExceptions(includeTaskCanceledExceptions);
if (exception != null)
{
UpdateExceptionObservedStatus();
@@ -1928,7 +1931,7 @@ namespace System.Threading.Tasks
/// <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)
+ 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
@@ -1940,7 +1943,7 @@ namespace System.Threading.Tasks
try
{
// Post the throwing of the exception to that context, and return.
- targetContext.Post(state => ((ExceptionDispatchInfo)state).Throw(), edi);
+ targetContext.Post(state => ((ExceptionDispatchInfo)state!).Throw(), edi);
return;
}
catch (Exception postException)
@@ -1962,7 +1965,7 @@ namespace System.Threading.Tasks
#endif
// Propagate the exception(s) on the ThreadPool
- ThreadPool.QueueUserWorkItem(state => ((ExceptionDispatchInfo)state).Throw(), edi);
+ ThreadPool.QueueUserWorkItem(state => ((ExceptionDispatchInfo)state!).Throw(), edi);
#endif // CORERT
}
@@ -1980,7 +1983,7 @@ namespace System.Threading.Tasks
/// </summary>
internal void UpdateExceptionObservedStatus()
{
- Task parent = m_contingentProperties?.m_parent;
+ Task? parent = m_contingentProperties?.m_parent;
if ((parent != null)
&& ((Options & TaskCreationOptions.AttachedToParent) != 0)
&& ((parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0)
@@ -2048,7 +2051,7 @@ namespace System.Threading.Tasks
}
else
{
- ContingentProperties props = m_contingentProperties;
+ ContingentProperties props = m_contingentProperties!;
// Count of 1 => either all children finished, or there were none. Safe to complete ourselves
// without paying the price of an Interlocked.Decrement.
@@ -2075,7 +2078,7 @@ namespace System.Threading.Tasks
// Now is the time to prune exceptional children. We'll walk the list and removes the ones whose exceptions we might have observed after they threw.
// we use a local variable for exceptional children here because some other thread may be nulling out m_contingentProperties.m_exceptionalChildren
- List<Task> exceptionalChildren = props.m_exceptionalChildren;
+ List<Task>? exceptionalChildren = props.m_exceptionalChildren;
if (exceptionalChildren != null)
{
lock (exceptionalChildren)
@@ -2096,7 +2099,7 @@ namespace System.Threading.Tasks
// At this point, the task is done executing and waiting for its children,
// we can transition our task to a completion state.
- ContingentProperties cp = Volatile.Read(ref m_contingentProperties);
+ ContingentProperties? cp = Volatile.Read(ref m_contingentProperties);
if (cp != null)
{
AddExceptionsFromChildren(cp);
@@ -2170,7 +2173,7 @@ namespace System.Threading.Tasks
// continuations hold onto the task, and therefore are keeping it alive.
m_action = null;
- ContingentProperties cp = m_contingentProperties;
+ ContingentProperties? cp = m_contingentProperties;
if (cp != null)
{
// Similarly, null out any ExecutionContext we may have captured,
@@ -2188,7 +2191,7 @@ namespace System.Threading.Tasks
internal void NotifyParentIfPotentiallyAttachedTask()
{
- Task parent = m_contingentProperties?.m_parent;
+ Task? parent = m_contingentProperties?.m_parent;
if (parent != null
&& ((parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0)
&& (((TaskCreationOptions)(m_stateFlags & OptionsMask)) & TaskCreationOptions.AttachedToParent) != 0)
@@ -2213,7 +2216,7 @@ namespace System.Threading.Tasks
if (childTask.IsFaulted && !childTask.IsExceptionObservedByParent)
{
// Lazily initialize the child exception list
- if (props.m_exceptionalChildren == null)
+ if (props!.m_exceptionalChildren == null)
{
Interlocked.CompareExchange(ref props.m_exceptionalChildren, new List<Task>(), null);
}
@@ -2222,7 +2225,7 @@ namespace System.Threading.Tasks
// multiple times for the same task. In that case, AddExceptionsFromChildren() could be nulling m_exceptionalChildren
// out at the same time that we're processing it, resulting in a NullReferenceException here. We'll protect
// ourselves by caching m_exceptionChildren in a local variable.
- List<Task> tmp = props.m_exceptionalChildren;
+ List<Task>? tmp = props.m_exceptionalChildren;
if (tmp != null)
{
lock (tmp)
@@ -2232,7 +2235,7 @@ namespace System.Threading.Tasks
}
}
- if (Interlocked.Decrement(ref props.m_completionCountdown) == 0)
+ if (Interlocked.Decrement(ref props!.m_completionCountdown) == 0)
{
// This call came from the final child to complete, and apparently we have previously given up this task's right to complete itself.
// So we need to invoke the final finish stage.
@@ -2253,7 +2256,7 @@ namespace System.Threading.Tasks
// simultaneously on the same task from two different contexts. This can result in m_exceptionalChildren
// being nulled out while it is being processed, which could lead to a NullReferenceException. To
// protect ourselves, we'll cache m_exceptionalChildren in a local variable.
- List<Task> exceptionalChildren = props.m_exceptionalChildren;
+ List<Task>? exceptionalChildren = props.m_exceptionalChildren;
if (exceptionalChildren != null)
{
@@ -2268,7 +2271,7 @@ namespace System.Threading.Tasks
Debug.Assert(task.IsCompleted, "Expected all tasks in list to be completed");
if (task.IsFaulted && !task.IsExceptionObservedByParent)
{
- TaskExceptionHolder exceptionHolder = Volatile.Read(ref task.m_contingentProperties).m_exceptionsHolder;
+ TaskExceptionHolder? exceptionHolder = Volatile.Read(ref task.m_contingentProperties)!.m_exceptionsHolder;
Debug.Assert(exceptionHolder != null);
// No locking necessary since child task is finished adding exceptions
@@ -2322,7 +2325,7 @@ namespace System.Threading.Tasks
/// </summary>
internal virtual void ExecuteFromThreadPool(Thread threadPoolThread) => ExecuteEntryUnsafe(threadPoolThread);
- internal void ExecuteEntryUnsafe(Thread threadPoolThread) // used instead of ExecuteEntry() when we don't have to worry about double-execution prevent
+ internal void ExecuteEntryUnsafe(Thread? threadPoolThread) // used instead of ExecuteEntry() when we don't have to worry about double-execution prevent
{
// Remember that we started running the task delegate.
m_stateFlags |= TASK_STATE_DELEGATE_INVOKED;
@@ -2350,10 +2353,10 @@ namespace System.Threading.Tasks
}
// A trick so we can refer to the TLS slot with a byref.
- private void ExecuteWithThreadLocal(ref Task currentTaskSlot, Thread threadPoolThread = null)
+ private void ExecuteWithThreadLocal(ref Task? currentTaskSlot, Thread? threadPoolThread = null)
{
// Remember the current task so we can restore it after running, and then
- Task previousTask = currentTaskSlot;
+ Task? previousTask = currentTaskSlot;
// ETW event for Task Started
var log = TplEventSource.Log;
@@ -2365,7 +2368,7 @@ namespace System.Threading.Tasks
EventSource.SetCurrentThreadActivityId(TplEventSource.CreateGuidForTaskID(this.Id), out savedActivityID);
// previousTask holds the actual "current task" we want to report in the event
if (previousTask != null)
- log.TaskStarted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id);
+ log.TaskStarted(previousTask.m_taskScheduler!.Id, previousTask.Id, this.Id);
else
log.TaskStarted(TaskScheduler.Current.Id, 0, this.Id);
}
@@ -2382,7 +2385,7 @@ namespace System.Threading.Tasks
// Execute the task body
try
{
- ExecutionContext ec = CapturedContext;
+ ExecutionContext? ec = CapturedContext;
if (ec == null)
{
// No context, just run the task directly.
@@ -2421,7 +2424,7 @@ namespace System.Threading.Tasks
{
// previousTask holds the actual "current task" we want to report in the event
if (previousTask != null)
- log.TaskCompleted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id, IsFaulted);
+ log.TaskCompleted(previousTask.m_taskScheduler!.Id, previousTask.Id, this.Id, IsFaulted);
else
log.TaskCompleted(TaskScheduler.Current.Id, 0, this.Id, IsFaulted);
@@ -2451,7 +2454,7 @@ namespace System.Threading.Tasks
return;
}
- if (m_action is Action<object> actionWithState)
+ if (m_action is Action<object?> actionWithState)
{
actionWithState(m_stateObject);
return;
@@ -2469,7 +2472,7 @@ namespace System.Threading.Tasks
Debug.Assert(unhandledException != null);
if (unhandledException is OperationCanceledException exceptionAsOce && IsCancellationRequested &&
- m_contingentProperties.m_cancellationToken == exceptionAsOce.CancellationToken)
+ m_contingentProperties!.m_cancellationToken == exceptionAsOce.CancellationToken)
{
// All conditions are satisfied for us to go into canceled state in Finish().
// Mark the acknowledgement. The exception is also stored to enable it to be
@@ -2526,7 +2529,7 @@ namespace System.Threading.Tasks
// Create the best AwaitTaskContinuation object given the request.
// If this remains null by the end of the function, we can use the
// continuationAction directly without wrapping it.
- TaskContinuation tc = null;
+ TaskContinuation? tc = null;
// If the user wants the continuation to run on the current "context" if there is one...
if (continueOnCapturedContext)
@@ -2605,7 +2608,7 @@ namespace System.Threading.Tasks
// fall back to using the state machine's delegate.
if (continueOnCapturedContext)
{
- SynchronizationContext syncCtx = SynchronizationContext.Current;
+ SynchronizationContext? syncCtx = SynchronizationContext.Current;
if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
{
var tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, stateMachineBox.MoveNextAction, flowExecutionContext: false);
@@ -2617,7 +2620,7 @@ namespace System.Threading.Tasks
}
else
{
- TaskScheduler scheduler = TaskScheduler.InternalCurrent;
+ TaskScheduler? scheduler = TaskScheduler.InternalCurrent;
if (scheduler != null && scheduler != TaskScheduler.Default)
{
var tc = new TaskSchedulerAwaitTaskContinuation(scheduler, stateMachineBox.MoveNextAction, flowExecutionContext: false);
@@ -2846,9 +2849,9 @@ namespace System.Threading.Tasks
bool etwIsEnabled = log.IsEnabled();
if (etwIsEnabled)
{
- Task currentTask = Task.InternalCurrent;
+ Task? currentTask = Task.InternalCurrent;
log.TaskWaitBegin(
- (currentTask != null ? currentTask.m_taskScheduler.Id : TaskScheduler.Default.Id), (currentTask != null ? currentTask.Id : 0),
+ (currentTask != null ? currentTask.m_taskScheduler!.Id : TaskScheduler.Default.Id), (currentTask != null ? currentTask.Id : 0),
this.Id, TplEventSource.TaskWaitBehavior.Synchronous, 0);
}
@@ -2877,10 +2880,10 @@ namespace System.Threading.Tasks
// ETW event for Task Wait End
if (etwIsEnabled)
{
- Task currentTask = Task.InternalCurrent;
+ Task? currentTask = Task.InternalCurrent;
if (currentTask != null)
{
- log.TaskWaitEnd(currentTask.m_taskScheduler.Id, currentTask.Id, this.Id);
+ log.TaskWaitEnd(currentTask.m_taskScheduler!.Id, currentTask.Id, this.Id);
}
else
{
@@ -2999,12 +3002,12 @@ namespace System.Threading.Tasks
bool bPopSucceeded = false;
bool mustCleanup = false;
- TaskSchedulerException tse = null;
+ TaskSchedulerException? tse = null;
// If started, and running in a task context, we can try to pop the chore.
if ((m_stateFlags & TASK_STATE_STARTED) != 0)
{
- TaskScheduler ts = m_taskScheduler;
+ TaskScheduler? ts = m_taskScheduler;
try
{
@@ -3095,7 +3098,7 @@ namespace System.Threading.Tasks
RecordInternalCancellationRequest();
Debug.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0, "Task.RecordInternalCancellationRequest(CancellationToken) only valid for promise-style task");
- Debug.Assert(m_contingentProperties.m_cancellationToken == default);
+ Debug.Assert(m_contingentProperties!.m_cancellationToken == default);
// Store the supplied cancellation token as this task's token.
// Waiting on this task will then result in an OperationCanceledException containing this token.
@@ -3108,7 +3111,7 @@ namespace System.Threading.Tasks
// Breaks out logic for recording a cancellation request
// This overload should only be used for promise tasks where no cancellation token
// was supplied when the task was created.
- internal void RecordInternalCancellationRequest(CancellationToken tokenToRecord, object cancellationException)
+ internal void RecordInternalCancellationRequest(CancellationToken tokenToRecord, object? cancellationException)
{
RecordInternalCancellationRequest(tokenToRecord);
@@ -3184,7 +3187,7 @@ namespace System.Threading.Tasks
TASK_STATE_COMPLETION_RESERVED | TASK_STATE_RAN_TO_COMPLETION,
TASK_STATE_COMPLETION_RESERVED | TASK_STATE_RAN_TO_COMPLETION | TASK_STATE_FAULTED | TASK_STATE_CANCELED))
{
- ContingentProperties props = m_contingentProperties;
+ ContingentProperties? props = m_contingentProperties;
if (props != null)
{
NotifyParentIfPotentiallyAttachedTask();
@@ -3252,7 +3255,7 @@ namespace System.Threading.Tasks
// If the tokenToRecord is not None, it will be stored onto the task.
// If the OperationCanceledException is not null, it will be stored into the task's exception holder.
// This method is only valid for promise tasks.
- internal bool TrySetCanceled(CancellationToken tokenToRecord, object cancellationException)
+ internal bool TrySetCanceled(CancellationToken tokenToRecord, object? cancellationException)
{
Debug.Assert(m_action == null, "Task<T>.TrySetCanceled(): non-null m_action");
Debug.Assert(
@@ -3296,7 +3299,7 @@ namespace System.Threading.Tasks
// Atomically store the fact that this task is completing. From this point on, the adding of continuations will
// result in the continuations being run/launched directly rather than being added to the continuation list.
// Then if we grabbed any continuations, run them.
- object continuationObject = Interlocked.Exchange(ref m_continuationObject, s_taskCompletionSentinel);
+ object? continuationObject = Interlocked.Exchange(ref m_continuationObject, s_taskCompletionSentinel);
if (continuationObject != null)
{
RunContinuations(continuationObject);
@@ -3352,7 +3355,7 @@ namespace System.Threading.Tasks
}
// Not a single; it must be a list.
- List<object> continuations = (List<object>)continuationObject;
+ List<object?> continuations = (List<object?>)continuationObject;
//
// Begin processing of continuation list
@@ -3384,7 +3387,7 @@ namespace System.Threading.Tasks
// and Action delegates, which are all by default implicitly synchronous.
for (int i = 0; i < continuationCount; i++)
{
- object currentContinuation = continuations[i];
+ object? currentContinuation = continuations[i];
if (currentContinuation == null)
{
continue;
@@ -3611,13 +3614,13 @@ namespace System.Threading.Tasks
CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
Task continuationTask = new ContinuationTaskFromTask(
- this, continuationAction, null,
+ this, continuationAction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
- ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+ ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
return continuationTask;
}
@@ -3642,7 +3645,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
- public Task ContinueWith(Action<Task, object> continuationAction, object state)
+ public Task ContinueWith(Action<Task, object?> continuationAction, object? state)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default, TaskContinuationOptions.None);
}
@@ -3668,7 +3671,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task ContinueWith(Action<Task, object> continuationAction, object state, CancellationToken cancellationToken)
+ public Task ContinueWith(Action<Task, object?> continuationAction, object? state, CancellationToken cancellationToken)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
@@ -3696,7 +3699,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- public Task ContinueWith(Action<Task, object> continuationAction, object state, TaskScheduler scheduler)
+ public Task ContinueWith(Action<Task, object?> continuationAction, object? state, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, state, scheduler, default, TaskContinuationOptions.None);
}
@@ -3730,7 +3733,7 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- public Task ContinueWith(Action<Task, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
+ public Task ContinueWith(Action<Task, object?> continuationAction, object? state, TaskContinuationOptions continuationOptions)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default, continuationOptions);
}
@@ -3774,14 +3777,14 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task ContinueWith(Action<Task, object> continuationAction, object state, CancellationToken cancellationToken,
+ public Task ContinueWith(Action<Task, object?> continuationAction, object? state, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, just with a stack mark parameter.
- private Task ContinueWith(Action<Task, object> continuationAction, object state, TaskScheduler scheduler,
+ private Task ContinueWith(Action<Task, object?> continuationAction, object? state, TaskScheduler scheduler,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null action
@@ -3801,13 +3804,13 @@ namespace System.Threading.Tasks
CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
Task continuationTask = new ContinuationTaskFromTask(
- this, continuationAction, state,
+ this, continuationAction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
- ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+ ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
return continuationTask;
}
@@ -4004,13 +4007,13 @@ namespace System.Threading.Tasks
CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
- this, continuationFunction, null,
+ this, continuationFunction!, null, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
- ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+ ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
return continuationTask;
}
@@ -4038,7 +4041,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
- public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state)
+ public Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state)
{
return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default,
TaskContinuationOptions.None);
@@ -4069,7 +4072,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken)
+ public Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state, CancellationToken cancellationToken)
{
return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
@@ -4100,7 +4103,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler)
+ public Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state, TaskScheduler scheduler)
{
return ContinueWith<TResult>(continuationFunction, state, scheduler, default, TaskContinuationOptions.None);
}
@@ -4137,7 +4140,7 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
+ public Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state, TaskContinuationOptions continuationOptions)
{
return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default, continuationOptions);
}
@@ -4184,14 +4187,14 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken,
+ public Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith<TResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, just with a stack mark parameter.
- private Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler,
+ private Task<TResult> ContinueWith<TResult>(Func<Task, object?, TResult> continuationFunction, object? state, TaskScheduler scheduler,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null function
@@ -4211,13 +4214,13 @@ namespace System.Threading.Tasks
CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
- this, continuationFunction, state,
+ this, continuationFunction!, state, // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
- ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+ ContinueWithCore(continuationTask, scheduler!, cancellationToken, continuationOptions); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
return continuationTask;
}
@@ -4386,13 +4389,13 @@ namespace System.Threading.Tasks
{
Debug.Assert(tc != null, "Expected non-null tc object in AddTaskContinuationComplex");
- object oldValue = m_continuationObject;
+ object? oldValue = m_continuationObject;
// Logic for the case where we were previously storing a single continuation
- if ((oldValue != s_taskCompletionSentinel) && (!(oldValue is List<object>)))
+ if ((oldValue != s_taskCompletionSentinel) && (!(oldValue is List<object?>)))
{
// Construct a new TaskContinuation list
- List<object> newList = new List<object>();
+ List<object?> newList = new List<object?>();
// Add in the old single value
newList.Add(oldValue);
@@ -4407,7 +4410,7 @@ namespace System.Threading.Tasks
// m_continuationObject is guaranteed at this point to be either a List or
// s_taskCompletionSentinel.
- List<object> list = m_continuationObject as List<object>;
+ List<object?>? list = m_continuationObject as List<object?>;
Debug.Assert((list != null) || (m_continuationObject == s_taskCompletionSentinel),
"Expected m_continuationObject to be list or sentinel");
@@ -4469,21 +4472,21 @@ namespace System.Threading.Tasks
{
// We need to snap a local reference to m_continuations since reading a volatile object is more costly.
// Also to prevent the value to be changed as result of a race condition with another method.
- object continuationsLocalRef = m_continuationObject;
+ object? continuationsLocalRef = m_continuationObject;
// Task is completed. Nothing to do here.
if (continuationsLocalRef == s_taskCompletionSentinel) return;
- if (!(continuationsLocalRef is List<object> continuationsLocalListRef))
+ if (!(continuationsLocalRef is List<object?> continuationsLocalListRef))
{
// This is not a list. If we have a single object (the one we want to remove) we try to replace it with an empty list.
// Note we cannot go back to a null state, since it will mess up the AddTaskContinuation logic.
- if (Interlocked.CompareExchange(ref m_continuationObject, new List<object>(), continuationObject) != continuationObject)
+ if (Interlocked.CompareExchange(ref m_continuationObject, new List<object?>(), continuationObject) != continuationObject)
{
// If we fail it means that either AddContinuationComplex won the race condition and m_continuationObject is now a List
// that contains the element we want to remove. Or FinishContinuations set the s_taskCompletionSentinel.
// So we should try to get a list one more time
- continuationsLocalListRef = m_continuationObject as List<object>;
+ continuationsLocalListRef = m_continuationObject as List<object?>;
}
else
{
@@ -4711,9 +4714,9 @@ namespace System.Threading.Tasks
// We make sure that the exception behavior of Task.Wait() is replicated the same for tasks handled in either of these codepaths
//
- List<Exception> exceptions = null;
- List<Task> waitedOnTaskList = null;
- List<Task> notificationTasks = null;
+ List<Exception>? exceptions = null;
+ List<Task>? waitedOnTaskList = null;
+ List<Task>? notificationTasks = null;
// If any of the waited-upon tasks end as Faulted or Canceled, set these to true.
bool exceptionSeen = false, cancellationSeen = false;
@@ -4721,7 +4724,7 @@ namespace System.Threading.Tasks
bool returnValue = true;
// Collects incomplete tasks in "waitedOnTaskList"
- for (int i = tasks.Length - 1; i >= 0; i--)
+ for (int i = tasks!.Length - 1; i >= 0; i--) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
Task task = tasks[i];
@@ -4730,7 +4733,7 @@ namespace System.Threading.Tasks
ThrowHelper.ThrowArgumentException(ExceptionResource.Task_WaitMulti_NullTask, ExceptionArgument.tasks);
}
- bool taskIsCompleted = task.IsCompleted;
+ bool taskIsCompleted = task!.IsCompleted; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
if (!taskIsCompleted)
{
// try inlining the task only if we have an infinite timeout and an empty cancellation token
@@ -4819,7 +4822,7 @@ namespace System.Threading.Tasks
/// <param name="item">The item to add.</param>
/// <param name="list">The list.</param>
/// <param name="initSize">The size to which to initialize the list if the list is null.</param>
- private static void AddToList<T>(T item, ref List<T> list, int initSize)
+ private static void AddToList<T>(T item, ref List<T>? list, int initSize)
{
if (list == null) list = new List<T>(initSize);
list.Add(item);
@@ -4897,9 +4900,9 @@ namespace System.Threading.Tasks
/// If the completed task is canceled or it has other exceptions, here we will add those
/// into the passed in exception list (which will be lazily initialized here).
/// </summary>
- internal static void AddExceptionsForCompletedTask(ref List<Exception> exceptions, Task t)
+ internal static void AddExceptionsForCompletedTask(ref List<Exception>? exceptions, Task t)
{
- AggregateException ex = t.GetExceptions(true);
+ AggregateException? ex = t.GetExceptions(true);
if (ex != null)
{
// make sure the task's exception observed status is set appropriately
@@ -5086,7 +5089,7 @@ namespace System.Threading.Tasks
// Make a pass through the loop to check for any tasks that may have
// already been completed, and to verify that no tasks are null.
- for (int taskIndex = 0; taskIndex < tasks.Length; taskIndex++)
+ for (int taskIndex = 0; taskIndex < tasks!.Length; taskIndex++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
Task task = tasks[taskIndex];
@@ -5095,7 +5098,7 @@ namespace System.Threading.Tasks
ThrowHelper.ThrowArgumentException(ExceptionResource.Task_WaitMulti_NullTask, ExceptionArgument.tasks);
}
- if (signaledTaskIndex == -1 && task.IsCompleted)
+ if (signaledTaskIndex == -1 && task!.IsCompleted) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
// We found our first completed task. Store it, but we can't just return here,
// as we still need to validate the whole array for nulls.
@@ -5147,7 +5150,7 @@ namespace System.Threading.Tasks
if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
var task = new Task();
- bool succeeded = task.TrySetException(exception);
+ bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
Debug.Assert(succeeded, "This should always succeed on a new task.");
return task;
}
@@ -5161,7 +5164,7 @@ namespace System.Threading.Tasks
if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
var task = new Task<TResult>();
- bool succeeded = task.TrySetException(exception);
+ bool succeeded = task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
Debug.Assert(succeeded, "This should always succeed on a new task.");
return task;
}
@@ -5184,7 +5187,7 @@ namespace System.Threading.Tasks
{
if (!cancellationToken.IsCancellationRequested)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.cancellationToken);
- return new Task<TResult>(true, default, TaskCreationOptions.None, cancellationToken);
+ return new Task<TResult>(true, default!, TaskCreationOptions.None, cancellationToken); // TODO-NULLABLE-GENERIC
}
/// <summary>Creates a <see cref="Task"/> that's completed due to cancellation with the specified exception.</summary>
@@ -5292,7 +5295,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="function"/> parameter was null.
/// </exception>
- public static Task Run(Func<Task> function)
+ public static Task Run(Func<Task?> function)
{
return Run(function, default);
}
@@ -5311,7 +5314,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">
/// The <see cref="T:System.CancellationTokenSource"/> associated with <paramref name="cancellationToken"/> was disposed.
/// </exception>
- public static Task Run(Func<Task> function, CancellationToken cancellationToken)
+ public static Task Run(Func<Task?> function, CancellationToken cancellationToken)
{
// Check arguments
if (function == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.function);
@@ -5321,7 +5324,7 @@ namespace System.Threading.Tasks
return Task.FromCanceled(cancellationToken);
// Kick off initial Task, which will call the user-supplied function and yield a Task.
- Task<Task> task1 = Task<Task>.Factory.StartNew(function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ Task<Task?> task1 = Task<Task?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
// Create a promise-style Task to be used as a proxy for the operation
// Set lookForOce == true so that unwrap logic can be on the lookout for OCEs thrown as faults from task1, to support in-delegate cancellation.
@@ -5340,7 +5343,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="function"/> parameter was null.
/// </exception>
- public static Task<TResult> Run<TResult>(Func<Task<TResult>> function)
+ public static Task<TResult> Run<TResult>(Func<Task<TResult>?> function)
{
return Run(function, default);
}
@@ -5356,7 +5359,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="function"/> parameter was null.
/// </exception>
- public static Task<TResult> Run<TResult>(Func<Task<TResult>> function, CancellationToken cancellationToken)
+ public static Task<TResult> Run<TResult>(Func<Task<TResult>?> function, CancellationToken cancellationToken)
{
// Check arguments
if (function == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.function);
@@ -5366,7 +5369,7 @@ namespace System.Threading.Tasks
return Task.FromCanceled<TResult>(cancellationToken);
// Kick off initial Task, which will call the user-supplied function and yield a Task.
- Task<Task<TResult>> task1 = Task<Task<TResult>>.Factory.StartNew(function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ Task<Task<TResult>?> task1 = Task<Task<TResult>?>.Factory.StartNew(function!, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
// Create a promise-style Task to be used as a proxy for the operation
// Set lookForOce == true so that unwrap logic can be on the lookout for OCEs thrown as faults from task1, to support in-delegate cancellation.
@@ -5475,7 +5478,7 @@ namespace System.Threading.Tasks
/// <summary>Task that also stores the completion closure and logic for Task.Delay implementation.</summary>
private class DelayPromise : Task
{
- private readonly TimerQueueTimer _timer;
+ private readonly TimerQueueTimer? _timer;
internal DelayPromise(int millisecondsDelay)
{
@@ -5489,7 +5492,7 @@ namespace System.Threading.Tasks
if (millisecondsDelay != Timeout.Infinite) // no need to create the timer if it's an infinite timeout
{
- _timer = new TimerQueueTimer(state => ((DelayPromise)state).CompleteTimedOut(), this, (uint)millisecondsDelay, Timeout.UnsignedInfinite, flowExecutionContext: false);
+ _timer = new TimerQueueTimer(state => ((DelayPromise)state!).CompleteTimedOut(), this, (uint)millisecondsDelay, Timeout.UnsignedInfinite, flowExecutionContext: false); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
if (IsCanceled)
{
// Handle rare race condition where cancellation occurs prior to our having created and stored the timer, in which case
@@ -5528,7 +5531,7 @@ namespace System.Threading.Tasks
Debug.Assert(token.CanBeCanceled);
_token = token;
- _registration = token.UnsafeRegister(state => ((DelayPromiseWithCancellation)state).CompleteCanceled(), this);
+ _registration = token.UnsafeRegister(state => ((DelayPromiseWithCancellation)state!).CompleteCanceled(), this); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
}
private void CompleteCanceled()
@@ -5593,7 +5596,7 @@ namespace System.Threading.Tasks
foreach (var task in tasks)
{
if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
- taskArray[index++] = task;
+ taskArray[index++] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
return InternalWhenAll(taskArray);
}
@@ -5601,10 +5604,10 @@ namespace System.Threading.Tasks
// Do some argument checking and convert tasks to a List (and later an array).
if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
List<Task> taskList = new List<Task>();
- foreach (Task task in tasks)
+ foreach (Task task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
- taskList.Add(task);
+ taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
// Delegate the rest to InternalWhenAll()
@@ -5643,7 +5646,7 @@ namespace System.Threading.Tasks
// Do some argument checking and make a defensive copy of the tasks array
if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
- int taskCount = tasks.Length;
+ int taskCount = tasks!.Length; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
if (taskCount == 0) return InternalWhenAll(tasks); // Small optimization in the case of an empty array.
Task[] tasksCopy = new Task[taskCount];
@@ -5651,7 +5654,7 @@ namespace System.Threading.Tasks
{
Task task = tasks[i];
if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
- tasksCopy[i] = task;
+ tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
// The rest can be delegated to InternalWhenAll()
@@ -5686,7 +5689,7 @@ namespace System.Threading.Tasks
/// Stores all of the constituent tasks. Tasks clear themselves out of this
/// array as they complete, but only if they don't have their wait notification bit set.
/// </summary>
- private readonly Task[] m_tasks;
+ private readonly Task?[] m_tasks;
/// <summary>The number of tasks remaining to complete.</summary>
private int m_count;
@@ -5720,8 +5723,8 @@ namespace System.Threading.Tasks
if (Interlocked.Decrement(ref m_count) == 0)
{
// Set up some accounting variables
- List<ExceptionDispatchInfo> observedExceptions = null;
- Task canceledTask = null;
+ List<ExceptionDispatchInfo>? observedExceptions = null;
+ Task? canceledTask = null;
// Loop through antecedents:
// If any one of them faults, the result will be faulted
@@ -5837,7 +5840,7 @@ namespace System.Threading.Tasks
foreach (var task in tasks)
{
if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
- taskArray[index++] = task;
+ taskArray[index++] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
return InternalWhenAll<TResult>(taskArray);
}
@@ -5845,10 +5848,10 @@ namespace System.Threading.Tasks
// Do some argument checking and convert tasks into a List (later an array)
if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
List<Task<TResult>> taskList = new List<Task<TResult>>();
- foreach (Task<TResult> task in tasks)
+ foreach (Task<TResult> task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
- taskList.Add(task);
+ taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
// Delegate the rest to InternalWhenAll<TResult>().
@@ -5890,7 +5893,7 @@ namespace System.Threading.Tasks
// Do some argument checking and make a defensive copy of the tasks array
if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
- int taskCount = tasks.Length;
+ int taskCount = tasks!.Length; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
if (taskCount == 0) return InternalWhenAll<TResult>(tasks); // small optimization in the case of an empty task array
Task<TResult>[] tasksCopy = new Task<TResult>[taskCount];
@@ -5898,7 +5901,7 @@ namespace System.Threading.Tasks
{
Task<TResult> task = tasks[i];
if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
- tasksCopy[i] = task;
+ tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
// Delegate the rest to InternalWhenAll<TResult>()
@@ -5925,7 +5928,7 @@ namespace System.Threading.Tasks
/// Stores all of the constituent tasks. Tasks clear themselves out of this
/// array as they complete, but only if they don't have their wait notification bit set.
/// </summary>
- private readonly Task<T>[] m_tasks;
+ private readonly Task<T>?[] m_tasks;
/// <summary>The number of tasks remaining to complete.</summary>
private int m_count;
@@ -5961,8 +5964,8 @@ namespace System.Threading.Tasks
{
// Set up some accounting variables
T[] results = new T[m_tasks.Length];
- List<ExceptionDispatchInfo> observedExceptions = null;
- Task canceledTask = null;
+ List<ExceptionDispatchInfo>? observedExceptions = null;
+ Task? canceledTask = null;
// Loop through antecedents:
// If any one of them faults, the result will be faulted
@@ -5970,7 +5973,7 @@ namespace System.Threading.Tasks
// If none fault or are canceled, then result will be RanToCompletion
for (int i = 0; i < m_tasks.Length; i++)
{
- Task<T> task = m_tasks[i];
+ Task<T>? task = m_tasks[i];
Debug.Assert(task != null, "Constituent task in WhenAll should never be null");
if (task.IsFaulted)
@@ -6057,7 +6060,7 @@ namespace System.Threading.Tasks
public static Task<Task> WhenAny(params Task[] tasks)
{
if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
- if (tasks.Length == 0)
+ if (tasks!.Length == 0) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks);
}
@@ -6070,7 +6073,7 @@ namespace System.Threading.Tasks
{
Task task = tasks[i];
if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
- tasksCopy[i] = task;
+ tasksCopy[i] = task!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
// Previously implemented CommonCWAnyLogic() can handle the rest
@@ -6099,10 +6102,10 @@ namespace System.Threading.Tasks
// Make a defensive copy, as the user may manipulate the tasks collection
// after we return but before the WhenAny asynchronously completes.
List<Task> taskList = new List<Task>();
- foreach (Task task in tasks)
+ foreach (Task task in tasks!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
- taskList.Add(task);
+ taskList.Add(task!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
if (taskList.Count == 0)
@@ -6183,7 +6186,7 @@ namespace System.Threading.Tasks
#if PROJECTN
[DependencyReductionRoot]
#endif
- internal virtual Delegate[] GetDelegateContinuationsForDebugger()
+ internal virtual Delegate[]? GetDelegateContinuationsForDebugger()
{
//Avoid an infinite loop by making sure the continuation object is not a reference to istelf.
if (m_continuationObject != this)
@@ -6192,7 +6195,7 @@ namespace System.Threading.Tasks
return null;
}
- private static Delegate[] GetDelegatesFromContinuationObject(object continuationObject)
+ private static Delegate[]? GetDelegatesFromContinuationObject(object? continuationObject)
{
if (continuationObject != null)
{
@@ -6209,7 +6212,7 @@ namespace System.Threading.Tasks
if (continuationObject is Task continuationTask)
{
Debug.Assert(continuationTask.m_action == null);
- Delegate[] delegates = continuationTask.GetDelegateContinuationsForDebugger();
+ Delegate[]? delegates = continuationTask.GetDelegateContinuationsForDebugger();
if (delegates != null)
return delegates;
}
@@ -6221,10 +6224,10 @@ namespace System.Threading.Tasks
return new Delegate[] { new Action<Task>(singleCompletionAction.Invoke) };
}
- if (continuationObject is List<object> continuationList)
+ if (continuationObject is List<object?> continuationList)
{
List<Delegate> result = new List<Delegate>();
- foreach (object obj in continuationList)
+ foreach (object? obj in continuationList)
{
var innerDelegates = GetDelegatesFromContinuationObject(obj);
if (innerDelegates != null)
@@ -6248,10 +6251,10 @@ namespace System.Threading.Tasks
[DependencyReductionRoot]
#endif
//Do not remove: VS debugger calls this API directly using func-eval to populate data in the tasks window
- private static Task GetActiveTaskFromId(int taskId)
+ private static Task? GetActiveTaskFromId(int taskId)
{
- Task task = null;
- s_currentActiveTasks.TryGetValue(taskId, out task);
+ Task? task = null;
+ s_currentActiveTasks?.TryGetValue(taskId, out task);
return task;
}
}
@@ -6283,9 +6286,9 @@ namespace System.Threading.Tasks
m_task = task;
}
- public object AsyncState { get { return m_task.AsyncState; } }
+ public object? AsyncState { get { return m_task.AsyncState; } }
public TaskCreationOptions CreationOptions { get { return m_task.CreationOptions; } }
- public Exception Exception { get { return m_task.Exception; } }
+ public Exception? Exception { get { return m_task.Exception; } }
public int Id { get { return m_task.Id; } }
public bool CancellationPending { get { return (m_task.Status == TaskStatus.WaitingToRun) && m_task.CancellationToken.IsCancellationRequested; } }
public TaskStatus Status { get { return m_task.Status; } }
@@ -6519,7 +6522,7 @@ namespace System.Threading.Tasks
private readonly bool _lookForOce;
public UnwrapPromise(Task outerTask, bool lookForOce)
- : base((object)null, outerTask.CreationOptions & TaskCreationOptions.AttachedToParent)
+ : base((object?)null, outerTask.CreationOptions & TaskCreationOptions.AttachedToParent)
{
Debug.Assert(outerTask != null, "Expected non-null outerTask");
_lookForOce = lookForOce;
@@ -6594,7 +6597,7 @@ namespace System.Threading.Tasks
ThreadPool.UnsafeQueueUserWorkItem(state =>
{
// InvokeCore(completingTask);
- var tuple = (Tuple<UnwrapPromise<TResult>, Task>)state;
+ var tuple = (Tuple<UnwrapPromise<TResult>, Task>)state!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
tuple.Item1.InvokeCore(tuple.Item2);
}, Tuple.Create<UnwrapPromise<TResult>, Task>(this, completingTask));
}
@@ -6648,7 +6651,7 @@ namespace System.Threading.Tasks
case TaskStatus.Faulted:
var edis = task.GetExceptionDispatchInfos();
ExceptionDispatchInfo oceEdi;
- OperationCanceledException oce;
+ OperationCanceledException? oce;
if (lookForOce && edis.Count > 0 &&
(oceEdi = edis[0]) != null &&
(oce = oceEdi.SourceException as OperationCanceledException) != null)
@@ -6670,7 +6673,7 @@ namespace System.Threading.Tasks
if (Task.s_asyncDebuggingEnabled)
RemoveFromActiveTasks(this);
- result = TrySetResult(taskTResult != null ? taskTResult.Result : default);
+ result = TrySetResult(taskTResult != null ? taskTResult.Result : default!); // TODO-NULLABLE-GENERIC
break;
}
return result;
@@ -6681,7 +6684,7 @@ namespace System.Threading.Tasks
/// transferring the appropriate results to ourself.
/// </summary>
/// <param name="task">The inner task returned by the task provided by the user.</param>
- private void ProcessInnerTask(Task task)
+ private void ProcessInnerTask(Task? task)
{
// If the inner task is null, the proxy should be canceled.
if (task == null)
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs
index c3ee31a53c..5147f116eb 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs
@@ -10,8 +10,7 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-using System;
-using System.Runtime.InteropServices;
+#nullable enable
using System.Runtime.Serialization;
namespace System.Threading.Tasks
@@ -24,7 +23,7 @@ namespace System.Threading.Tasks
public class TaskCanceledException : OperationCanceledException
{
[NonSerialized]
- private readonly Task _canceledTask; // The task which has been canceled.
+ private readonly Task? _canceledTask; // The task which has been canceled.
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskCanceledException"/> class.
@@ -38,7 +37,7 @@ namespace System.Threading.Tasks
/// class with a specified error message.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
- public TaskCanceledException(string message) : base(message)
+ public TaskCanceledException(string? message) : base(message)
{
}
@@ -49,7 +48,7 @@ namespace System.Threading.Tasks
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception.</param>
- public TaskCanceledException(string message, Exception innerException) : base(message, innerException)
+ public TaskCanceledException(string? message, Exception? innerException) : base(message, innerException)
{
}
@@ -61,7 +60,7 @@ namespace System.Threading.Tasks
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception.</param>
/// <param name="token">The <see cref="CancellationToken"/> that triggered the cancellation.</param>
- public TaskCanceledException(string message, Exception innerException, CancellationToken token) : base(message, innerException, token)
+ public TaskCanceledException(string? message, Exception? innerException, CancellationToken token) : base(message, innerException, token)
{
}
@@ -70,7 +69,7 @@ namespace System.Threading.Tasks
/// with a reference to the <see cref="T:System.Threading.Tasks.Task"/> that has been canceled.
/// </summary>
/// <param name="task">A task that has been canceled.</param>
- public TaskCanceledException(Task task) :
+ public TaskCanceledException(Task? task) :
base(SR.TaskCanceledException_ctor_DefaultMessage, task != null ? task.CancellationToken : new CancellationToken())
{
_canceledTask = task;
@@ -94,6 +93,6 @@ namespace System.Threading.Tasks
/// <see cref="T:System.Threading.Tasks.TaskCanceledException"/>, in which case
/// this property will return null.
/// </remarks>
- public Task Task => _canceledTask;
+ public Task? Task => _canceledTask;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs
index c85a44f974..045486a6a1 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs
@@ -11,6 +11,7 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+#nullable enable
using System;
using System.Diagnostics;
using System.Collections.Generic;
@@ -81,7 +82,7 @@ namespace System.Threading.Tasks
/// </summary>
/// <param name="state">The state to use as the underlying
/// <see cref="T:System.Threading.Tasks.Task{TResult}"/>'s AsyncState.</param>
- public TaskCompletionSource(object state)
+ public TaskCompletionSource(object? state)
: this(state, TaskCreationOptions.None)
{
}
@@ -98,7 +99,7 @@ namespace System.Threading.Tasks
/// The <paramref name="creationOptions"/> represent options invalid for use
/// with a <see cref="TaskCompletionSource{TResult}"/>.
/// </exception>
- public TaskCompletionSource(object state, TaskCreationOptions creationOptions)
+ public TaskCompletionSource(object? state, TaskCreationOptions creationOptions)
{
_task = new Task<TResult>(state, creationOptions);
}
@@ -150,7 +151,7 @@ namespace System.Threading.Tasks
{
if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
- bool rval = _task.TrySetException(exception);
+ bool rval = _task.TrySetException(exception!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
if (!rval && !_task.IsCompleted) SpinUntilCompleted();
return rval;
}
@@ -180,11 +181,11 @@ namespace System.Threading.Tasks
if (exceptions == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exceptions);
List<Exception> defensiveCopy = new List<Exception>();
- foreach (Exception e in exceptions)
+ foreach (Exception e in exceptions!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
if (e == null)
ThrowHelper.ThrowArgumentException(ExceptionResource.TaskCompletionSourceT_TrySetException_NullException, ExceptionArgument.exceptions);
- defensiveCopy.Add(e);
+ defensiveCopy.Add(e!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
}
if (defensiveCopy.Count == 0)
@@ -216,7 +217,7 @@ namespace System.Threading.Tasks
{
if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
- if (!TrySetException(exception))
+ if (!TrySetException(exception!)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted);
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs
index 63ae2bd815..0968a747b1 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs
@@ -2,9 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Security;
+#nullable enable
using System.Diagnostics;
-using System.Runtime.ExceptionServices;
using System.Runtime.CompilerServices;
namespace System.Threading.Tasks
@@ -12,13 +11,13 @@ namespace System.Threading.Tasks
// Task type used to implement: Task ContinueWith(Action<Task,...>)
internal sealed class ContinuationTaskFromTask : Task
{
- private Task m_antecedent;
+ private Task? m_antecedent;
public ContinuationTaskFromTask(
- Task antecedent, Delegate action, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
+ Task antecedent, Delegate action, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
base(action, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null)
{
- Debug.Assert(action is Action<Task> || action is Action<Task, object>,
+ Debug.Assert(action is Action<Task> || action is Action<Task, object?>,
"Invalid delegate type in ContinuationTaskFromTask");
m_antecedent = antecedent;
}
@@ -30,7 +29,7 @@ namespace System.Threading.Tasks
{
// Get and null out the antecedent. This is crucial to avoid a memory
// leak with long chains of continuations.
- var antecedent = m_antecedent;
+ Task? antecedent = m_antecedent;
Debug.Assert(antecedent != null,
"No antecedent was set for the ContinuationTaskFromTask.");
m_antecedent = null;
@@ -46,7 +45,7 @@ namespace System.Threading.Tasks
return;
}
- if (m_action is Action<Task, object> actionWithState)
+ if (m_action is Action<Task, object?> actionWithState)
{
actionWithState(antecedent, m_stateObject);
return;
@@ -58,13 +57,13 @@ namespace System.Threading.Tasks
// Task type used to implement: Task<TResult> ContinueWith(Func<Task,...>)
internal sealed class ContinuationResultTaskFromTask<TResult> : Task<TResult>
{
- private Task m_antecedent;
+ private Task? m_antecedent;
public ContinuationResultTaskFromTask(
- Task antecedent, Delegate function, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
+ Task antecedent, Delegate function, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
base(function, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null)
{
- Debug.Assert(function is Func<Task, TResult> || function is Func<Task, object, TResult>,
+ Debug.Assert(function is Func<Task, TResult> || function is Func<Task, object?, TResult>,
"Invalid delegate type in ContinuationResultTaskFromTask");
m_antecedent = antecedent;
}
@@ -76,7 +75,7 @@ namespace System.Threading.Tasks
{
// Get and null out the antecedent. This is crucial to avoid a memory
// leak with long chains of continuations.
- var antecedent = m_antecedent;
+ Task? antecedent = m_antecedent;
Debug.Assert(antecedent != null,
"No antecedent was set for the ContinuationResultTaskFromTask.");
m_antecedent = null;
@@ -92,7 +91,7 @@ namespace System.Threading.Tasks
return;
}
- if (m_action is Func<Task, object, TResult> funcWithState)
+ if (m_action is Func<Task, object?, TResult> funcWithState)
{
m_result = funcWithState(antecedent, m_stateObject);
return;
@@ -104,13 +103,13 @@ namespace System.Threading.Tasks
// Task type used to implement: Task ContinueWith(Action<Task<TAntecedentResult>,...>)
internal sealed class ContinuationTaskFromResultTask<TAntecedentResult> : Task
{
- private Task<TAntecedentResult> m_antecedent;
+ private Task<TAntecedentResult>? m_antecedent;
public ContinuationTaskFromResultTask(
- Task<TAntecedentResult> antecedent, Delegate action, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
+ Task<TAntecedentResult> antecedent, Delegate action, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
base(action, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null)
{
- Debug.Assert(action is Action<Task<TAntecedentResult>> || action is Action<Task<TAntecedentResult>, object>,
+ Debug.Assert(action is Action<Task<TAntecedentResult>> || action is Action<Task<TAntecedentResult>, object?>,
"Invalid delegate type in ContinuationTaskFromResultTask");
m_antecedent = antecedent;
}
@@ -122,7 +121,7 @@ namespace System.Threading.Tasks
{
// Get and null out the antecedent. This is crucial to avoid a memory
// leak with long chains of continuations.
- var antecedent = m_antecedent;
+ Task<TAntecedentResult>? antecedent = m_antecedent;
Debug.Assert(antecedent != null,
"No antecedent was set for the ContinuationTaskFromResultTask.");
m_antecedent = null;
@@ -138,7 +137,7 @@ namespace System.Threading.Tasks
return;
}
- if (m_action is Action<Task<TAntecedentResult>, object> actionWithState)
+ if (m_action is Action<Task<TAntecedentResult>, object?> actionWithState)
{
actionWithState(antecedent, m_stateObject);
return;
@@ -150,13 +149,13 @@ namespace System.Threading.Tasks
// Task type used to implement: Task<TResult> ContinueWith(Func<Task<TAntecedentResult>,...>)
internal sealed class ContinuationResultTaskFromResultTask<TAntecedentResult, TResult> : Task<TResult>
{
- private Task<TAntecedentResult> m_antecedent;
+ private Task<TAntecedentResult>? m_antecedent;
public ContinuationResultTaskFromResultTask(
- Task<TAntecedentResult> antecedent, Delegate function, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
+ Task<TAntecedentResult> antecedent, Delegate function, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
base(function, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null)
{
- Debug.Assert(function is Func<Task<TAntecedentResult>, TResult> || function is Func<Task<TAntecedentResult>, object, TResult>,
+ Debug.Assert(function is Func<Task<TAntecedentResult>, TResult> || function is Func<Task<TAntecedentResult>, object?, TResult>,
"Invalid delegate type in ContinuationResultTaskFromResultTask");
m_antecedent = antecedent;
}
@@ -168,7 +167,7 @@ namespace System.Threading.Tasks
{
// Get and null out the antecedent. This is crucial to avoid a memory
// leak with long chains of continuations.
- var antecedent = m_antecedent;
+ Task<TAntecedentResult>? antecedent = m_antecedent;
Debug.Assert(antecedent != null,
"No antecedent was set for the ContinuationResultTaskFromResultTask.");
m_antecedent = null;
@@ -184,7 +183,7 @@ namespace System.Threading.Tasks
return;
}
- if (m_action is Func<Task<TAntecedentResult>, object, TResult> funcWithState)
+ if (m_action is Func<Task<TAntecedentResult>, object?, TResult> funcWithState)
{
m_result = funcWithState(antecedent, m_stateObject);
return;
@@ -283,7 +282,7 @@ namespace System.Threading.Tasks
m_options = options;
m_taskScheduler = scheduler;
if (AsyncCausalityTracer.LoggingOn)
- AsyncCausalityTracer.TraceOperationCreation(m_task, "Task.ContinueWith: " + task.m_action.Method.Name);
+ AsyncCausalityTracer.TraceOperationCreation(m_task, "Task.ContinueWith: " + task.m_action!.Method.Name);
if (Task.s_asyncDebuggingEnabled)
Task.AddToActiveTasks(m_task);
@@ -343,7 +342,7 @@ namespace System.Threading.Tasks
else continuationTask.InternalCancel(false);
}
- internal override Delegate[] GetDelegateContinuationsForDebugger()
+ internal override Delegate[]? GetDelegateContinuationsForDebugger()
{
if (m_task.m_action == null)
{
@@ -358,9 +357,13 @@ namespace System.Threading.Tasks
internal sealed class SynchronizationContextAwaitTaskContinuation : AwaitTaskContinuation
{
/// <summary>SendOrPostCallback delegate to invoke the action.</summary>
- private static readonly SendOrPostCallback s_postCallback = state => ((Action)state)(); // can't use InvokeAction as it's SecurityCritical
+ private static readonly SendOrPostCallback s_postCallback = state =>
+ {
+ Debug.Assert(state is Action);
+ ((Action)state)();
+ };
/// <summary>Cached delegate for PostAction</summary>
- private static ContextCallback s_postActionCallback;
+ private static ContextCallback? s_postActionCallback;
/// <summary>The context with which to run the action.</summary>
private readonly SynchronizationContext m_syncContext;
@@ -403,8 +406,9 @@ namespace System.Threading.Tasks
/// <summary>Calls InvokeOrPostAction(false) on the supplied SynchronizationContextAwaitTaskContinuation.</summary>
/// <param name="state">The SynchronizationContextAwaitTaskContinuation.</param>
- private static void PostAction(object state)
+ private static void PostAction(object? state)
{
+ Debug.Assert(state is SynchronizationContextAwaitTaskContinuation);
var c = (SynchronizationContextAwaitTaskContinuation)state;
TplEventSource log = TplEventSource.Log;
@@ -438,7 +442,7 @@ namespace System.Threading.Tasks
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ContextCallback GetPostActionCallback()
{
- ContextCallback callback = s_postActionCallback;
+ ContextCallback? callback = s_postActionCallback;
if (callback == null) { s_postActionCallback = callback = PostAction; } // lazily initialize SecurityCritical delegate
return callback;
}
@@ -489,7 +493,7 @@ namespace System.Threading.Tasks
{
try
{
- ((Action)state)();
+ ((Action)state!)(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
}
catch (Exception exception)
{
@@ -515,7 +519,7 @@ namespace System.Threading.Tasks
internal class AwaitTaskContinuation : TaskContinuation, IThreadPoolWorkItem
{
/// <summary>The ExecutionContext with which to run the continuation.</summary>
- private readonly ExecutionContext m_capturedContext;
+ private readonly ExecutionContext? m_capturedContext;
/// <summary>The action to invoke.</summary>
protected readonly Action m_action;
@@ -539,7 +543,7 @@ namespace System.Threading.Tasks
/// <param name="state">The state to pass to the action. Must not be null.</param>
/// <param name="scheduler">The scheduler to target.</param>
/// <returns>The created task.</returns>
- protected Task CreateTask(Action<object> action, object state, TaskScheduler scheduler)
+ protected Task CreateTask(Action<object?> action, object? state, TaskScheduler scheduler)
{
Debug.Assert(action != null);
Debug.Assert(scheduler != null);
@@ -615,7 +619,7 @@ namespace System.Threading.Tasks
void IThreadPoolWorkItem.Execute()
{
var log = TplEventSource.Log;
- ExecutionContext context = m_capturedContext;
+ ExecutionContext? context = m_capturedContext;
if (!log.IsEnabled() && context == null)
{
@@ -659,7 +663,11 @@ namespace System.Threading.Tasks
}
/// <summary>Cached delegate that invokes an Action passed as an object parameter.</summary>
- private readonly static ContextCallback s_invokeContextCallback = (state) => ((Action)state)();
+ private readonly static ContextCallback s_invokeContextCallback = (state) =>
+ {
+ Debug.Assert(state is Action);
+ ((Action)state)();
+ };
private readonly static Action<Action> s_invokeAction = (action) => action();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -669,7 +677,7 @@ namespace System.Threading.Tasks
/// <param name="callback">The callback to run.</param>
/// <param name="state">The state to pass to the callback.</param>
/// <param name="currentTask">A reference to Task.t_currentTask.</param>
- protected void RunCallback(ContextCallback callback, object state, ref Task currentTask)
+ protected void RunCallback(ContextCallback callback, object? state, ref Task? currentTask)
{
Debug.Assert(callback != null);
Debug.Assert(currentTask == Task.t_currentTask);
@@ -681,7 +689,7 @@ namespace System.Threading.Tasks
{
if (prevCurrentTask != null) currentTask = null;
- ExecutionContext context = m_capturedContext;
+ ExecutionContext? context = m_capturedContext;
if (context == null)
{
// If there's no captured context, just run the callback directly.
@@ -717,8 +725,8 @@ namespace System.Threading.Tasks
/// </remarks>
internal static void RunOrScheduleAction(Action action, bool allowInlining)
{
- ref Task currentTask = ref Task.t_currentTask;
- Task prevCurrentTask = currentTask;
+ ref Task? currentTask = ref Task.t_currentTask;
+ Task? prevCurrentTask = currentTask;
// If we're not allowed to run here, schedule the action
if (!allowInlining || !IsValidLocationForInlining)
@@ -753,8 +761,8 @@ namespace System.Threading.Tasks
// Same logic as in the RunOrScheduleAction(Action, ...) overload, except invoking
// box.Invoke instead of action().
- ref Task currentTask = ref Task.t_currentTask;
- Task prevCurrentTask = currentTask;
+ ref Task? currentTask = ref Task.t_currentTask;
+ Task? prevCurrentTask = currentTask;
// If we're not allowed to run here, schedule the action
if (!allowInlining || !IsValidLocationForInlining)
@@ -798,7 +806,7 @@ namespace System.Threading.Tasks
/// <summary>Schedules the action to be executed. No ExecutionContext work is performed used.</summary>
/// <param name="action">The action to invoke or queue.</param>
/// <param name="task">The task scheduling the action.</param>
- internal static void UnsafeScheduleAction(Action action, Task task)
+ internal static void UnsafeScheduleAction(Action action, Task? task)
{
AwaitTaskContinuation atc = new AwaitTaskContinuation(action, flowExecutionContext: false);
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExceptionHolder.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExceptionHolder.cs
index 67b4220b8d..d35e6a2e67 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExceptionHolder.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExceptionHolder.cs
@@ -10,6 +10,7 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+#nullable enable
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
@@ -33,9 +34,9 @@ namespace System.Threading.Tasks
/// The lazily-initialized list of faulting exceptions. Volatile
/// so that it may be read to determine whether any exceptions were stored.
/// </summary>
- private volatile List<ExceptionDispatchInfo> m_faultExceptions;
+ private volatile List<ExceptionDispatchInfo>? m_faultExceptions;
/// <summary>An exception that triggered the task to cancel.</summary>
- private ExceptionDispatchInfo m_cancellationException;
+ private ExceptionDispatchInfo? m_cancellationException;
/// <summary>Whether the holder was "observed" and thus doesn't cause finalization behavior.</summary>
private volatile bool m_isHandled;
@@ -252,7 +253,7 @@ namespace System.Threading.Tasks
/// <param name="calledFromFinalizer">Whether this is being called from a finalizer.</param>
/// <param name="includeThisException">An extra exception to be included (optionally).</param>
/// <returns>The aggregate exception to throw.</returns>
- internal AggregateException CreateExceptionObject(bool calledFromFinalizer, Exception includeThisException)
+ internal AggregateException CreateExceptionObject(bool calledFromFinalizer, Exception? includeThisException)
{
var exceptions = m_faultExceptions;
Debug.Assert(exceptions != null, "Expected an initialized list.");
@@ -284,7 +285,7 @@ namespace System.Threading.Tasks
/// </summary>
internal ReadOnlyCollection<ExceptionDispatchInfo> GetExceptionDispatchInfos()
{
- var exceptions = m_faultExceptions;
+ List<ExceptionDispatchInfo>? exceptions = m_faultExceptions;
Debug.Assert(exceptions != null, "Expected an initialized list.");
Debug.Assert(exceptions.Count > 0, "Expected at least one exception.");
MarkAsHandled(false);
@@ -298,7 +299,7 @@ namespace System.Threading.Tasks
/// <returns>
/// The ExceptionDispatchInfo for the cancellation exception. May be null.
/// </returns>
- internal ExceptionDispatchInfo GetCancellationExceptionDispatchInfo()
+ internal ExceptionDispatchInfo? GetCancellationExceptionDispatchInfo()
{
var edi = m_cancellationException;
Debug.Assert(edi == null || edi.SourceException is OperationCanceledException,
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExtensions.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExtensions.cs
index 75b4b0a378..4b45f75c98 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExtensions.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExtensions.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.Collections.Generic;
using System.Runtime.CompilerServices;
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskFactory.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskFactory.cs
index f7816d6206..cc5a5a1aa1 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskFactory.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskFactory.cs
@@ -12,6 +12,7 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+#nullable enable
using System;
using System.Collections.Generic;
using System.Security;
@@ -40,18 +41,18 @@ namespace System.Threading.Tasks
{
// member variables
private readonly CancellationToken m_defaultCancellationToken;
- private readonly TaskScheduler m_defaultScheduler;
+ private readonly TaskScheduler? m_defaultScheduler;
private readonly TaskCreationOptions m_defaultCreationOptions;
private readonly TaskContinuationOptions m_defaultContinuationOptions;
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)
{
return
m_defaultScheduler ??
- (currTask != null && (currTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0 ? currTask.ExecutingTaskScheduler :
+ (currTask != null && (currTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0 ? currTask.ExecutingTaskScheduler! : // a "current" task must be executing, which means it must have a scheduler
TaskScheduler.Default);
}
@@ -119,7 +120,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)
{
}
@@ -190,7 +191,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)
{
CheckMultiTaskContinuationOptions(continuationOptions);
CheckCreationOptions(creationOptions);
@@ -239,7 +240,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
@@ -281,7 +282,7 @@ namespace System.Threading.Tasks
/// </remarks>
public Task StartNew(Action action)
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask),
m_defaultCreationOptions, InternalTaskOptions.None);
}
@@ -306,7 +307,7 @@ namespace System.Threading.Tasks
/// </remarks>
public Task StartNew(Action action, CancellationToken cancellationToken)
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, null, cancellationToken, GetDefaultScheduler(currTask),
m_defaultCreationOptions, InternalTaskOptions.None);
}
@@ -334,7 +335,7 @@ namespace System.Threading.Tasks
/// </remarks>
public Task StartNew(Action action, TaskCreationOptions creationOptions)
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask), creationOptions,
InternalTaskOptions.None);
}
@@ -396,9 +397,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 StartNew(Action<object> action, object state)
+ public Task StartNew(Action<object?> action, object? state) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
m_defaultCreationOptions, InternalTaskOptions.None);
}
@@ -425,9 +426,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 StartNew(Action<object> action, object state, CancellationToken cancellationToken)
+ public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, state, cancellationToken, GetDefaultScheduler(currTask),
m_defaultCreationOptions, InternalTaskOptions.None);
}
@@ -455,9 +456,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 StartNew(Action<object> action, object state, TaskCreationOptions creationOptions)
+ public Task StartNew(Action<object?> action, object? state, TaskCreationOptions creationOptions) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
{
- Task currTask = Task.InternalCurrent;
+ Task? currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
creationOptions, InternalTaskOptions.None);
}
@@ -496,7 +497,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 StartNew(Action<object> action, object state, CancellationToken cancellationToken,
+ public Task StartNew(Action<object?> action, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
return Task.InternalStartNew(
@@ -525,7 +526,7 @@ namespace System.Threading.Tasks
/// </remarks>
public Task<TResult> StartNew<TResult>(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));
}
@@ -556,7 +557,7 @@ namespace System.Threading.Tasks
/// </remarks>
public Task<TResult> StartNew<TResult>(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));
}
@@ -588,7 +589,7 @@ namespace System.Threading.Tasks
/// </remarks>
public Task<TResult> StartNew<TResult>(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));
}
@@ -657,9 +658,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<TResult>(Func<object, TResult> function, object state)
+ public Task<TResult> StartNew<TResult>(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));
}
@@ -690,9 +691,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<TResult>(Func<object, TResult> function, object state, CancellationToken cancellationToken)
+ public Task<TResult> StartNew<TResult>(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));
}
@@ -724,9 +725,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<TResult>(Func<object, TResult> function, object state, TaskCreationOptions creationOptions)
+ public Task<TResult> StartNew<TResult>(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));
}
@@ -769,7 +770,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<TResult>(Func<object, TResult> function, object state, CancellationToken cancellationToken,
+ public Task<TResult> StartNew<TResult>(Func<object?, TResult> function, object? state, CancellationToken cancellationToken, // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
return Task<TResult>.StartNew(
@@ -879,9 +880,9 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task FromAsync(
- Func<AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<AsyncCallback, object?, IAsyncResult> beginMethod,
Action<IAsyncResult> endMethod,
- object state)
+ object? state)
{
return FromAsync(beginMethod, endMethod, state, m_defaultCreationOptions);
}
@@ -909,8 +910,8 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task FromAsync(
- Func<AsyncCallback, object, IAsyncResult> beginMethod,
- Action<IAsyncResult> endMethod, object state, TaskCreationOptions creationOptions)
+ Func<AsyncCallback, object?, IAsyncResult> beginMethod,
+ Action<IAsyncResult> endMethod, object? state, TaskCreationOptions creationOptions)
{
return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, state, creationOptions);
}
@@ -938,10 +939,10 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task FromAsync<TArg1>(
- Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
Action<IAsyncResult> endMethod,
TArg1 arg1,
- object state)
+ object? state)
{
return FromAsync(beginMethod, endMethod, arg1, state, m_defaultCreationOptions);
}
@@ -974,9 +975,9 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task FromAsync<TArg1>(
- Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
Action<IAsyncResult> endMethod,
- TArg1 arg1, object state, TaskCreationOptions creationOptions)
+ TArg1 arg1, object? state, TaskCreationOptions creationOptions)
{
return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, arg1, state, creationOptions);
}
@@ -1008,9 +1009,9 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task FromAsync<TArg1, TArg2>(
- Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
Action<IAsyncResult> endMethod,
- TArg1 arg1, TArg2 arg2, object state)
+ TArg1 arg1, TArg2 arg2, object? state)
{
return FromAsync(beginMethod, endMethod, arg1, arg2, state, m_defaultCreationOptions);
}
@@ -1047,9 +1048,9 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task FromAsync<TArg1, TArg2>(
- Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
Action<IAsyncResult> endMethod,
- TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
+ TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions)
{
return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, arg1, arg2, state, creationOptions);
}
@@ -1085,9 +1086,9 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task FromAsync<TArg1, TArg2, TArg3>(
- Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
Action<IAsyncResult> endMethod,
- TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
+ TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state)
{
return FromAsync(beginMethod, endMethod, arg1, arg2, arg3, state, m_defaultCreationOptions);
}
@@ -1128,9 +1129,9 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task FromAsync<TArg1, TArg2, TArg3>(
- Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
Action<IAsyncResult> endMethod,
- TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+ TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state, TaskCreationOptions creationOptions)
{
return TaskFactory<VoidTaskResult>.FromAsyncImpl<TArg1, TArg2, TArg3>(beginMethod, null, endMethod, arg1, arg2, arg3, state, creationOptions);
}
@@ -1243,8 +1244,8 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TResult>(
- Func<AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endMethod, object state)
+ Func<AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, object? state)
{
return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, state, m_defaultCreationOptions);
}
@@ -1275,8 +1276,8 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TResult>(
- 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)
{
return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, state, creationOptions);
}
@@ -1306,8 +1307,8 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TArg1, TResult>(
- Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object state)
+ Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object? state)
{
return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, state, m_defaultCreationOptions);
}
@@ -1341,8 +1342,8 @@ namespace System.Threading.Tasks
/// <remarks>
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
- public Task<TResult> FromAsync<TArg1, TResult>(Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object state, TaskCreationOptions creationOptions)
+ public Task<TResult> FromAsync<TArg1, TResult>(Func<TArg1, AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object? state, TaskCreationOptions creationOptions)
{
return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, state, creationOptions);
}
@@ -1375,8 +1376,8 @@ namespace System.Threading.Tasks
/// <remarks>
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
- public Task<TResult> FromAsync<TArg1, TArg2, TResult>(Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state)
+ public Task<TResult> FromAsync<TArg1, TArg2, TResult>(Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object? state)
{
return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, m_defaultCreationOptions);
}
@@ -1415,8 +1416,8 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TArg1, TArg2, TResult>(
- Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
+ Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object? state, TaskCreationOptions creationOptions)
{
return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, creationOptions);
}
@@ -1454,8 +1455,8 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult>(
- Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state)
{
return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, m_defaultCreationOptions);
}
@@ -1498,8 +1499,8 @@ namespace System.Threading.Tasks
/// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
/// </remarks>
public Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult>(
- Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
- Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object?, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state, TaskCreationOptions creationOptions)
{
return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, creationOptions);
}
@@ -2284,7 +2285,7 @@ namespace System.Threading.Tasks
private const int CompletedFlag = 0b_01;
private const int SyncBlockingFlag = 0b_10;
- private IList<Task> _tasks; // must track this for cleanup
+ private IList<Task>? _tasks; // must track this for cleanup
private int _stateFlags;
public CompleteOnInvokePromise(IList<Task> tasks, bool isSyncBlocking) : base()
@@ -2331,7 +2332,8 @@ namespace System.Threading.Tasks
// This may also help to avoided unnecessary invocations of this whenComplete delegate.
// Note that we may be attempting to remove a continuation from a task that hasn't had it
// added yet; while there's overhead there, the operation won't hurt anything.
- var tasks = _tasks;
+ IList<Task>? tasks = _tasks;
+ Debug.Assert(tasks != null, "Should not have been nulled out yet.");
int numTasks = tasks.Count;
for (int i = 0; i < numTasks; i++)
{
@@ -2411,8 +2413,8 @@ namespace System.Threading.Tasks
internal static void CommonCWAnyLogicCleanup(Task<Task> continuation)
{
// Force cleanup of the promise (e.g. removing continuations from each
- // constituent task), by completing the promise with any value.
- ((CompleteOnInvokePromise)continuation).Invoke(null);
+ // constituent task), by completing the promise with any value (it's not observable).
+ ((CompleteOnInvokePromise)continuation).Invoke(null!);
}
/// <summary>
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskScheduler.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskScheduler.cs
index 1d1a581b0b..d8940044da 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskScheduler.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskScheduler.cs
@@ -10,6 +10,7 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+#nullable enable
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
@@ -142,7 +143,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.NotSupportedException">
/// This scheduler is unable to generate a list of queued tasks at this time.
/// </exception>
- protected abstract IEnumerable<Task> GetScheduledTasks();
+ protected abstract IEnumerable<Task>? GetScheduledTasks();
/// <summary>
/// Indicates the maximum concurrency level this
@@ -174,7 +175,7 @@ namespace System.Threading.Tasks
// Do not inline unstarted tasks (i.e., task.ExecutingTaskScheduler == null).
// Do not inline TaskCompletionSource-style (a.k.a. "promise") tasks.
// No need to attempt inlining if the task body was already run (i.e. either TASK_STATE_DELEGATE_INVOKED or TASK_STATE_CANCELED bits set)
- TaskScheduler ets = task.ExecutingTaskScheduler;
+ TaskScheduler? ets = task.ExecutingTaskScheduler;
// Delegate cross-scheduler inlining requests to target scheduler
if (ets != this && ets != null) return ets.TryRunInline(task, taskWasPreviouslyQueued);
@@ -254,7 +255,7 @@ namespace System.Threading.Tasks
//
// The global container that keeps track of TaskScheduler instances for debugging purposes.
- private static ConditionalWeakTable<TaskScheduler, object> s_activeTaskSchedulers;
+ private static ConditionalWeakTable<TaskScheduler, object?>? s_activeTaskSchedulers;
// An AppDomain-wide default manager.
private static readonly TaskScheduler s_defaultTaskScheduler = new ThreadPoolTaskScheduler();
@@ -292,13 +293,13 @@ namespace System.Threading.Tasks
/// <summary>Adds this scheduler ot the active schedulers tracking collection for debugging purposes.</summary>
private void AddToActiveTaskSchedulers()
{
- ConditionalWeakTable<TaskScheduler, object> activeTaskSchedulers = s_activeTaskSchedulers;
+ ConditionalWeakTable<TaskScheduler, object?>? activeTaskSchedulers = s_activeTaskSchedulers;
if (activeTaskSchedulers == null)
{
- Interlocked.CompareExchange(ref s_activeTaskSchedulers, new ConditionalWeakTable<TaskScheduler, object>(), null);
+ Interlocked.CompareExchange(ref s_activeTaskSchedulers, new ConditionalWeakTable<TaskScheduler, object?>(), null);
activeTaskSchedulers = s_activeTaskSchedulers;
}
- activeTaskSchedulers.Add(this, null);
+ activeTaskSchedulers!.Add(this, null); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761
}
/// <summary>
@@ -323,8 +324,7 @@ namespace System.Threading.Tasks
{
get
{
- TaskScheduler current = InternalCurrent;
- return current ?? TaskScheduler.Default;
+ return InternalCurrent ?? Default;
}
}
@@ -335,11 +335,11 @@ namespace System.Threading.Tasks
/// <remarks>
/// When not called from within a task, <see cref="InternalCurrent"/> will return null.
/// </remarks>
- internal static TaskScheduler InternalCurrent
+ internal static TaskScheduler? InternalCurrent
{
get
{
- Task currentTask = Task.InternalCurrent;
+ Task? currentTask = Task.InternalCurrent;
return ((currentTask != null)
&& ((currentTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
) ? currentTask.ExecutingTaskScheduler : null;
@@ -472,11 +472,11 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.NotSupportedException">
/// This scheduler is unable to generate a list of queued tasks at this time.
/// </exception>
- internal Task[] GetScheduledTasksForDebugger()
+ internal Task[]? GetScheduledTasksForDebugger()
{
// this can throw InvalidOperationException indicating that they are unable to provide the info
// at the moment. We should let the debugger receive that exception so that it can indicate it in the UI
- IEnumerable<Task> activeTasksSource = GetScheduledTasks();
+ IEnumerable<Task>? activeTasksSource = GetScheduledTasks();
if (activeTasksSource == null)
return null;
@@ -553,7 +553,7 @@ namespace System.Threading.Tasks
}
// returns the scheduler's GetScheduledTasks
- public IEnumerable<Task> ScheduledTasks
+ public IEnumerable<Task>? ScheduledTasks
{
get { return m_taskScheduler.GetScheduledTasks(); }
}
@@ -578,15 +578,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.InvalidOperationException">This constructor expects <see cref="T:System.Threading.SynchronizationContext.Current"/> to be set.</exception>
internal SynchronizationContextTaskScheduler()
{
- SynchronizationContext synContext = SynchronizationContext.Current;
-
- // make sure we have a synccontext to work with
- if (synContext == null)
- {
+ m_synchronizationContext = SynchronizationContext.Current ??
+ // make sure we have a synccontext to work with
throw new InvalidOperationException(SR.TaskScheduler_FromCurrentSynchronizationContext_NoCurrent);
- }
-
- m_synchronizationContext = synContext;
}
/// <summary>
@@ -615,11 +609,12 @@ namespace System.Threading.Tasks
return TryExecuteTask(task);
}
else
+ {
return false;
+ }
}
- // not implemented
- protected override IEnumerable<Task> GetScheduledTasks()
+ protected override IEnumerable<Task>? GetScheduledTasks()
{
return null;
}
@@ -640,7 +635,11 @@ namespace System.Threading.Tasks
}
// preallocated SendOrPostCallback delegate
- private static readonly SendOrPostCallback s_postCallback = s => ((Task)s).ExecuteEntry(); // with double-execute check because SC could be buggy
+ private static readonly SendOrPostCallback s_postCallback = s =>
+ {
+ Debug.Assert(s is Task);
+ ((Task)s).ExecuteEntry(); // with double-execute check because SC could be buggy
+ };
}
/// <summary>
@@ -655,7 +654,7 @@ namespace System.Threading.Tasks
/// </remarks>
public class UnobservedTaskExceptionEventArgs : EventArgs
{
- private AggregateException m_exception;
+ private AggregateException? m_exception;
internal bool m_observed = false;
/// <summary>
@@ -663,7 +662,7 @@ namespace System.Threading.Tasks
/// with the unobserved exception.
/// </summary>
/// <param name="exception">The Exception that has gone unobserved.</param>
- public UnobservedTaskExceptionEventArgs(AggregateException exception) { m_exception = exception; }
+ public UnobservedTaskExceptionEventArgs(AggregateException? exception) { m_exception = exception; }
/// <summary>
/// Marks the <see cref="Exception"/> as "observed," thus preventing it
@@ -679,6 +678,6 @@ namespace System.Threading.Tasks
/// <summary>
/// The Exception that went unobserved.
/// </summary>
- public AggregateException Exception { get { return m_exception; } }
+ public AggregateException? Exception { get { return m_exception; } }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskSchedulerException.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskSchedulerException.cs
index 85ec497219..c68469c5cd 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskSchedulerException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskSchedulerException.cs
@@ -10,8 +10,7 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-using System;
-using System.Runtime.InteropServices;
+#nullable enable
using System.Runtime.Serialization;
namespace System.Threading.Tasks
@@ -36,7 +35,7 @@ namespace System.Threading.Tasks
/// class with a specified error message.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
- public TaskSchedulerException(string message) : base(message)
+ public TaskSchedulerException(string? message) : base(message)
{
}
@@ -46,7 +45,7 @@ namespace System.Threading.Tasks
/// this exception.
/// </summary>
/// <param name="innerException">The exception that is the cause of the current exception.</param>
- public TaskSchedulerException(Exception innerException)
+ public TaskSchedulerException(Exception? innerException)
: base(SR.TaskSchedulerException_ctor_DefaultMessage, innerException)
{
}
@@ -58,7 +57,7 @@ namespace System.Threading.Tasks
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception.</param>
- public TaskSchedulerException(string message, Exception innerException) : base(message, innerException)
+ public TaskSchedulerException(string? message, Exception? innerException) : base(message, innerException)
{
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskToApm.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskToApm.cs
index add41f588e..110520a32b 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskToApm.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskToApm.cs
@@ -16,6 +16,7 @@
// return TaskToApm.End<int>(asyncResult);
// }
+#nullable enable
using System.Diagnostics;
namespace System.Threading.Tasks
@@ -33,7 +34,7 @@ namespace System.Threading.Tasks
/// <param name="callback">The callback to be invoked upon completion.</param>
/// <param name="state">The state to be stored in the IAsyncResult.</param>
/// <returns>An IAsyncResult to represent the task's asynchronous operation.</returns>
- public static IAsyncResult Begin(Task task, AsyncCallback callback, object state)
+ public static IAsyncResult Begin(Task task, AsyncCallback callback, object? state)
{
Debug.Assert(task != null);
@@ -63,7 +64,7 @@ namespace System.Threading.Tasks
/// <param name="asyncResult">The IAsyncResult to unwrap.</param>
public static void End(IAsyncResult asyncResult)
{
- Task task;
+ Task? task;
// If the IAsyncResult is our task-wrapping IAsyncResult, extract the Task.
var twar = asyncResult as TaskWrapperAsyncResult;
@@ -91,7 +92,7 @@ namespace System.Threading.Tasks
/// <param name="asyncResult">The IAsyncResult to unwrap.</param>
public static TResult End<TResult>(IAsyncResult asyncResult)
{
- Task<TResult> task;
+ Task<TResult>? task;
// If the IAsyncResult is our task-wrapping IAsyncResult, extract the Task.
var twar = asyncResult as TaskWrapperAsyncResult;
@@ -158,7 +159,7 @@ namespace System.Threading.Tasks
/// <summary>The wrapped Task.</summary>
internal readonly Task Task;
/// <summary>The new AsyncState value.</summary>
- private readonly object _state;
+ private readonly object? _state;
/// <summary>The new CompletedSynchronously value.</summary>
private readonly bool _completedSynchronously;
@@ -166,7 +167,7 @@ namespace System.Threading.Tasks
/// <param name="task">The Task to wrap.</param>
/// <param name="state">The new AsyncState value</param>
/// <param name="completedSynchronously">The new CompletedSynchronously value.</param>
- internal TaskWrapperAsyncResult(Task task, object state, bool completedSynchronously)
+ internal TaskWrapperAsyncResult(Task task, object? state, bool completedSynchronously)
{
Debug.Assert(task != null);
Debug.Assert(!completedSynchronously || task.IsCompleted, "If completedSynchronously is true, the task must be completed.");
@@ -180,7 +181,7 @@ namespace System.Threading.Tasks
// - IsCompleted and AsyncWaitHandle just pass through to the Task.
// - AsyncState and CompletedSynchronously return the corresponding values stored in this object.
- object IAsyncResult.AsyncState { get { return _state; } }
+ object? IAsyncResult.AsyncState { get { return _state; } }
bool IAsyncResult.CompletedSynchronously { get { return _completedSynchronously; } }
bool IAsyncResult.IsCompleted { get { return this.Task.IsCompleted; } }
WaitHandle IAsyncResult.AsyncWaitHandle { get { return ((IAsyncResult)this.Task).AsyncWaitHandle; } }
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ThreadPoolTaskScheduler.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ThreadPoolTaskScheduler.cs
index 9ab28ef34a..05cb75bcbc 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ThreadPoolTaskScheduler.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ThreadPoolTaskScheduler.cs
@@ -11,11 +11,9 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-using System;
-using System.Security;
-using System.Diagnostics;
+#nullable enable
using System.Collections.Generic;
-using System.Text;
+using System.Diagnostics;
namespace System.Threading.Tasks
{
@@ -33,7 +31,11 @@ namespace System.Threading.Tasks
}
// static delegate for threads allocated to handle LongRunning tasks.
- private static readonly ParameterizedThreadStart s_longRunningThreadWork = s => ((Task)s).ExecuteEntryUnsafe(threadPoolThread: null);
+ private static readonly ParameterizedThreadStart s_longRunningThreadWork = s =>
+ {
+ Debug.Assert(s is Task);
+ ((Task)s).ExecuteEntryUnsafe(threadPoolThread: null);
+ };
/// <summary>
/// Schedules a task to the ThreadPool.
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TplEventSource.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TplEventSource.cs
index 94f0ec37e8..184cc32890 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TplEventSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TplEventSource.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.Runtime.CompilerServices;
using System.Diagnostics.Tracing;
using Internal.Runtime.CompilerServices;
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs
index e9285ce45f..1b175614e2 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.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.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
@@ -63,7 +64,7 @@ namespace System.Threading.Tasks
internal static Task CompletedTask => Task.CompletedTask;
/// <summary>null if representing a successful synchronous completion, otherwise a <see cref="Task"/> or a <see cref="IValueTaskSource"/>.</summary>
- internal readonly object _obj;
+ internal readonly object? _obj;
/// <summary>Opaque value passed through to the <see cref="IValueTaskSource"/>.</summary>
internal readonly short _token;
/// <summary>true to continue on the capture context; otherwise, true.</summary>
@@ -106,7 +107,7 @@ namespace System.Threading.Tasks
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private ValueTask(object obj, short token, bool continueOnCapturedContext)
+ private ValueTask(object? obj, short token, bool continueOnCapturedContext)
{
_obj = obj;
_token = token;
@@ -117,7 +118,7 @@ namespace System.Threading.Tasks
public override int GetHashCode() => _obj?.GetHashCode() ?? 0;
/// <summary>Returns a value indicating whether this value is equal to a specified <see cref="object"/>.</summary>
- public override bool Equals(object obj) =>
+ public override bool Equals(object? obj) =>
obj is ValueTask &&
Equals((ValueTask)obj);
@@ -141,7 +142,7 @@ namespace System.Threading.Tasks
/// </remarks>
public Task AsTask()
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
return
obj == null ? CompletedTask :
@@ -200,7 +201,7 @@ namespace System.Threading.Tasks
/// <summary>Type used to create a <see cref="Task"/> to represent a <see cref="IValueTaskSource"/>.</summary>
private sealed class ValueTaskSourceAsTask : Task
{
- private static readonly Action<object> s_completionAction = state =>
+ private static readonly Action<object?> s_completionAction = state =>
{
if (!(state is ValueTaskSourceAsTask vtst) ||
!(vtst._source is IValueTaskSource source))
@@ -240,11 +241,11 @@ namespace System.Threading.Tasks
};
/// <summary>The associated <see cref="IValueTaskSource"/>.</summary>
- private IValueTaskSource _source;
+ private IValueTaskSource? _source;
/// <summary>The token to pass through to operations on <see cref="_source"/></summary>
private readonly short _token;
- public ValueTaskSourceAsTask(IValueTaskSource source, short token)
+ internal ValueTaskSourceAsTask(IValueTaskSource source, short token)
{
_token = token;
_source = source;
@@ -258,7 +259,7 @@ namespace System.Threading.Tasks
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
if (obj == null)
@@ -281,7 +282,7 @@ namespace System.Threading.Tasks
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
if (obj == null)
@@ -303,7 +304,7 @@ namespace System.Threading.Tasks
{
get
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
if (obj == null)
@@ -330,7 +331,7 @@ namespace System.Threading.Tasks
{
get
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
if (obj == null)
@@ -352,7 +353,7 @@ namespace System.Threading.Tasks
[StackTraceHidden]
internal void ThrowIfCompletedUnsuccessfully()
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
if (obj != null)
@@ -411,9 +412,9 @@ namespace System.Threading.Tasks
public readonly struct ValueTask<TResult> : IEquatable<ValueTask<TResult>>
{
/// <summary>A task canceled using `new CancellationToken(true)`. Lazily created only when first needed.</summary>
- private static Task<TResult> s_canceledTask;
+ private static Task<TResult>? s_canceledTask;
/// <summary>null if <see cref="_result"/> has the result, otherwise a <see cref="Task{TResult}"/> or a <see cref="IValueTaskSource{TResult}"/>.</summary>
- internal readonly object _obj;
+ internal readonly object? _obj;
/// <summary>The result to be used if the operation completed successfully synchronously.</summary>
internal readonly TResult _result;
/// <summary>Opaque value passed through to the <see cref="IValueTaskSource{TResult}"/>.</summary>
@@ -449,7 +450,7 @@ namespace System.Threading.Tasks
_obj = task;
- _result = default;
+ _result = default!; // TODO-NULLABLE-GENERIC
_continueOnCapturedContext = true;
_token = 0;
}
@@ -468,7 +469,7 @@ namespace System.Threading.Tasks
_obj = source;
_token = token;
- _result = default;
+ _result = default!; // TODO-NULLABLE-GENERIC
_continueOnCapturedContext = true;
}
@@ -478,7 +479,7 @@ namespace System.Threading.Tasks
/// <param name="token">The token.</param>
/// <param name="continueOnCapturedContext">true to continue on captured context; otherwise, false.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private ValueTask(object obj, TResult result, short token, bool continueOnCapturedContext)
+ private ValueTask(object? obj, TResult result, short token, bool continueOnCapturedContext)
{
_obj = obj;
_result = result;
@@ -494,7 +495,7 @@ namespace System.Threading.Tasks
0;
/// <summary>Returns a value indicating whether this value is equal to a specified <see cref="object"/>.</summary>
- public override bool Equals(object obj) =>
+ public override bool Equals(object? obj) =>
obj is ValueTask<TResult> &&
Equals((ValueTask<TResult>)obj);
@@ -521,7 +522,7 @@ namespace System.Threading.Tasks
/// </remarks>
public Task<TResult> AsTask()
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
if (obj == null)
@@ -572,11 +573,11 @@ namespace System.Threading.Tasks
return task;
}
- Task<TResult> canceledTask = s_canceledTask;
+ Task<TResult>? canceledTask = s_canceledTask;
if (canceledTask == null)
{
// Benign race condition to initialize cached task, as identity doesn't matter.
- s_canceledTask = Task.FromCanceled<TResult>(new CancellationToken(true));
+ s_canceledTask = canceledTask = Task.FromCanceled<TResult>(new CancellationToken(true));
}
return canceledTask;
}
@@ -593,7 +594,7 @@ namespace System.Threading.Tasks
/// <summary>Type used to create a <see cref="Task{TResult}"/> to represent a <see cref="IValueTaskSource{TResult}"/>.</summary>
private sealed class ValueTaskSourceAsTask : Task<TResult>
{
- private static readonly Action<object> s_completionAction = state =>
+ private static readonly Action<object?> s_completionAction = state =>
{
if (!(state is ValueTaskSourceAsTask vtst) ||
!(vtst._source is IValueTaskSource<TResult> source))
@@ -632,7 +633,7 @@ namespace System.Threading.Tasks
};
/// <summary>The associated <see cref="IValueTaskSource"/>.</summary>
- private IValueTaskSource<TResult> _source;
+ private IValueTaskSource<TResult>? _source;
/// <summary>The token to pass through to operations on <see cref="_source"/></summary>
private readonly short _token;
@@ -650,7 +651,7 @@ namespace System.Threading.Tasks
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
if (obj == null)
@@ -673,7 +674,7 @@ namespace System.Threading.Tasks
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
if (obj == null)
@@ -695,7 +696,7 @@ namespace System.Threading.Tasks
{
get
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
if (obj == null)
@@ -722,7 +723,7 @@ namespace System.Threading.Tasks
{
get
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
if (obj == null)
@@ -745,7 +746,7 @@ namespace System.Threading.Tasks
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
- object obj = _obj;
+ object? obj = _obj;
Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
if (obj == null)
@@ -776,7 +777,7 @@ namespace System.Threading.Tasks
new ConfiguredValueTaskAwaitable<TResult>(new ValueTask<TResult>(_obj, _result, _token, continueOnCapturedContext));
/// <summary>Gets a string-representation of this <see cref="ValueTask{TResult}"/>.</summary>
- public override string ToString()
+ public override string? ToString()
{
if (IsCompletedSuccessfully)
{
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Timer.cs b/src/System.Private.CoreLib/shared/System/Threading/Timer.cs
index a21203070f..66d01ac81a 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Timer.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Timer.cs
@@ -718,7 +718,7 @@ namespace System.Threading
{
private const uint MAX_SUPPORTED_TIMEOUT = (uint)0xfffffffe;
- private TimerHolder _timer = null!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
+ private TimerHolder _timer = null!; // initialized in helper called by ctors
public Timer(TimerCallback callback,
object? state,
diff --git a/src/System.Private.CoreLib/src/System/Delegate.cs b/src/System.Private.CoreLib/src/System/Delegate.cs
index 77dcea5a76..b281c9244e 100644
--- a/src/System.Private.CoreLib/src/System/Delegate.cs
+++ b/src/System.Private.CoreLib/src/System/Delegate.cs
@@ -20,7 +20,7 @@ namespace System
// MethodBase, either cached after first request or assigned from a DynamicMethod
// For open delegates to collectible types, this may be a LoaderAllocator object
- internal object _methodBase = null!; // Initialized by VM as needed
+ internal object? _methodBase; // Initialized by VM as needed
// _methodPtr is a pointer to the method we will invoke
// It could be a small thunk if this is a static or UM call
diff --git a/src/System.Private.CoreLib/src/System/MulticastDelegate.cs b/src/System.Private.CoreLib/src/System/MulticastDelegate.cs
index dfb8ceaaeb..e128c7597b 100644
--- a/src/System.Private.CoreLib/src/System/MulticastDelegate.cs
+++ b/src/System.Private.CoreLib/src/System/MulticastDelegate.cs
@@ -578,7 +578,7 @@ namespace System
{
if (target == null)
ThrowNullThisInDelegateToInstance();
- this._target = target!; // TODO-NULLABLE: Compiler can't see throw helper above
+ this._target = target!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
this._methodPtr = methodPtr;
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/AsyncCausalityTracer.cs b/src/System.Private.CoreLib/src/System/Threading/Tasks/AsyncCausalityTracer.cs
index d72ca12b70..491916699f 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/AsyncCausalityTracer.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Tasks/AsyncCausalityTracer.cs
@@ -2,16 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Security;
+#nullable enable
using System.Diagnostics;
using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
using System.Runtime.InteropServices.WindowsRuntime;
-
using WFD = Windows.Foundation.Diagnostics;
-
namespace System.Threading.Tasks
{
internal static class AsyncCausalityTracer
@@ -64,7 +60,7 @@ namespace System.Threading.Tasks
//COM Interface GUID {50850B26-267E-451B-A890-AB6A370245EE}
Guid guid = new Guid(0x50850B26, 0x267E, 0x451B, 0xA8, 0x90, 0XAB, 0x6A, 0x37, 0x02, 0x45, 0xEE);
- object factory = null;
+ object? factory = null;
try
{
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs b/src/System.Private.CoreLib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs
index a09279c06c..131fffc348 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs
@@ -2,9 +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;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;