diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs index 4e8ce691bec..f22b9d94bf6 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs @@ -35,10 +35,10 @@ public ConfiguredValueTaskAwaiter GetAwaiter() => /// Provides an awaiter for a . [StructLayout(LayoutKind.Auto)] - public struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion, IConfiguredValueTaskAwaiter + public readonly struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion, IConfiguredValueTaskAwaiter { /// The value being awaited. - private ValueTask _value; // Methods are called on this; avoid making it readonly so as to avoid unnecessary copies + private readonly ValueTask _value; /// The value to pass to ConfigureAwait. internal readonly bool _continueOnCapturedContext; @@ -74,7 +74,11 @@ public void UnsafeOnCompleted(Action continuation) => /// Gets the task underlying the incomplete . /// This method is used when awaiting and IsCompleted returned false; thus we expect the value task to be wrapping a non-null task. - (Task task, bool continueOnCapturedContext) IConfiguredValueTaskAwaiter.GetTask() => (_value.AsTaskExpectNonNull(), _continueOnCapturedContext); + Task IConfiguredValueTaskAwaiter.GetTask(out bool continueOnCapturedContext) + { + continueOnCapturedContext = _continueOnCapturedContext; + return _value.AsTaskExpectNonNull(); + } } } @@ -83,6 +87,6 @@ public void UnsafeOnCompleted(Action continuation) => /// internal interface IConfiguredValueTaskAwaiter { - (Task task, bool continueOnCapturedContext) GetTask(); + Task GetTask(out bool continueOnCapturedContext); } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs index 7bc8b5cc7d3..3f212d8bf9b 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs @@ -8,10 +8,10 @@ namespace System.Runtime.CompilerServices { /// Provides an awaiter for a . - public struct ValueTaskAwaiter : ICriticalNotifyCompletion, IValueTaskAwaiter + public readonly struct ValueTaskAwaiter : ICriticalNotifyCompletion, IValueTaskAwaiter { /// The value being awaited. - private ValueTask _value; // Methods are called on this; avoid making it readonly so as to avoid unnecessary copies + private readonly ValueTask _value; /// Initializes the awaiter. /// The value to be awaited. 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 de9b016328c..5edd8501b0c 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; -using System.ComponentModel; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -77,7 +76,7 @@ public ValueTask(Task task) } _task = task; - _result = default(TResult); + _result = default; } /// Returns the hash code for this instance. @@ -114,7 +113,12 @@ public Task AsTask() => // Return the task if we were constructed from one, otherwise manufacture one. We don't // cache the generated task into _task as it would end up changing both equality comparison // and the hash code we generate in GetHashCode. - _task ?? AsyncTaskMethodBuilder.GetTaskForResult(_result); + _task ?? +#if netstandard + Task.FromResult(_result); +#else + AsyncTaskMethodBuilder.GetTaskForResult(_result); +#endif internal Task AsTaskExpectNonNull() => // Return the task if we were constructed from one, otherwise manufacture one. @@ -123,13 +127,24 @@ internal Task AsTaskExpectNonNull() => _task ?? GetTaskForResultNoInlining(); [MethodImpl(MethodImplOptions.NoInlining)] - private Task GetTaskForResultNoInlining() => AsyncTaskMethodBuilder.GetTaskForResult(_result); + private Task GetTaskForResultNoInlining() => +#if netstandard + Task.FromResult(_result); +#else + AsyncTaskMethodBuilder.GetTaskForResult(_result); +#endif /// Gets whether the represents a completed operation. public bool IsCompleted => _task == null || _task.IsCompleted; /// Gets whether the represents a successfully completed operation. - public bool IsCompletedSuccessfully => _task == null || _task.IsCompletedSuccessfully; + public bool IsCompletedSuccessfully => + _task == null || +#if netstandard + _task.Status == TaskStatus.RanToCompletion; +#else + _task.IsCompletedSuccessfully; +#endif /// Gets whether the represents a failed operation. public bool IsFaulted => _task != null && _task.IsFaulted; @@ -153,26 +168,16 @@ public ConfiguredValueTaskAwaitable ConfigureAwait(bool continueOnCaptu /// Gets a string-representation of this . public override string ToString() { - if (_task != null) + if (IsCompletedSuccessfully) { - return _task.IsCompletedSuccessfully && _task.Result != null ? - _task.Result.ToString() : - string.Empty; + TResult result = Result; + if (result != null) + { + return result.ToString(); + } } - else - { - return _result != null ? - _result.ToString() : - string.Empty; - } - } - // TODO https://github.com/dotnet/corefx/issues/22171: - // Remove CreateAsyncMethodBuilder once the C# compiler relies on the AsyncBuilder attribute. - - /// Creates a method builder for use with an async method. - /// The created builder. - [EditorBrowsable(EditorBrowsableState.Never)] // intended only for compiler consumption - public static AsyncValueTaskMethodBuilder CreateAsyncMethodBuilder() => AsyncValueTaskMethodBuilder.Create(); + return string.Empty; + } } }