System.Threading.Tasks.Extensions by Microsoft

<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.0" />

 ValueTask<TResult>

public struct ValueTask<TResult> : IEquatable<ValueTask<TResult>>
Provides a value type that can represent a synchronously available value or a task object.
using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading.Tasks.Sources; namespace System.Threading.Tasks { [StructLayout(LayoutKind.Auto)] [AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder<>))] public readonly struct ValueTask<TResult> : IEquatable<ValueTask<TResult>> { private sealed class ValueTaskSourceAsTask : TaskCompletionSource<TResult> { private static readonly Action<object> s_completionAction = delegate(object state) { ValueTaskSourceAsTask valueTaskSourceAsTask = state as ValueTaskSourceAsTask; if (valueTaskSourceAsTask != null) { IValueTaskSource<TResult> source = valueTaskSourceAsTask._source; if (source != null) { valueTaskSourceAsTask._source = null; ValueTaskSourceStatus status = source.GetStatus(valueTaskSourceAsTask._token); try { valueTaskSourceAsTask.TrySetResult(source.GetResult(valueTaskSourceAsTask._token)); } catch (Exception exception) { if (status == ValueTaskSourceStatus.Canceled) valueTaskSourceAsTask.TrySetCanceled(); else valueTaskSourceAsTask.TrySetException(exception); } return; } } System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.state); }; private IValueTaskSource<TResult> _source; private readonly short _token; public ValueTaskSourceAsTask(IValueTaskSource<TResult> source, short token) { _source = source; _token = token; source.OnCompleted(s_completionAction, this, token, ValueTaskSourceOnCompletedFlags.None); } } private static Task<TResult> s_canceledTask; internal readonly object _obj; internal readonly TResult _result; internal readonly short _token; internal readonly bool _continueOnCapturedContext; public bool IsCompleted { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { object obj = _obj; if (obj == null) return true; return (obj as Task<TResult>)?.IsCompleted ?? (Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) != ValueTaskSourceStatus.Pending); } } public bool IsCompletedSuccessfully { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { object obj = _obj; if (obj == null) return true; Task<TResult> task = obj as Task<TResult>; if (task != null) return task.Status == TaskStatus.RanToCompletion; return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Succeeded; } } public bool IsFaulted { get { object obj = _obj; if (obj == null) return false; return (obj as Task<TResult>)?.IsFaulted ?? (Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Faulted); } } public bool IsCanceled { get { object obj = _obj; if (obj == null) return false; return (obj as Task<TResult>)?.IsCanceled ?? (Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Canceled); } } public TResult Result { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { object obj = _obj; if (obj == null) return _result; Task<TResult> task = obj as Task<TResult>; if (task != null) return task.GetAwaiter().GetResult(); return Unsafe.As<IValueTaskSource<TResult>>(obj).GetResult(_token); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask(TResult result) { _result = result; _obj = null; _continueOnCapturedContext = true; _token = 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask(Task<TResult> task) { if (task == null) System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.task); _obj = task; _result = default(TResult); _continueOnCapturedContext = true; _token = 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask(IValueTaskSource<TResult> source, short token) { if (source == null) System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.source); _obj = source; _token = token; _result = default(TResult); _continueOnCapturedContext = true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private ValueTask(object obj, TResult result, short token, bool continueOnCapturedContext) { _obj = obj; _result = result; _token = token; _continueOnCapturedContext = continueOnCapturedContext; } public override int GetHashCode() { if (_obj == null) { if (_result == null) return 0; return _result.GetHashCode(); } return _obj.GetHashCode(); } public override bool Equals(object obj) { if (obj is ValueTask<TResult>) return Equals((ValueTask<TResult>)obj); return false; } public bool Equals(ValueTask<TResult> other) { if (_obj == null && other._obj == null) return EqualityComparer<TResult>.Default.Equals(_result, other._result); if (_obj == other._obj) return _token == other._token; return false; } public static bool operator ==(ValueTask<TResult> left, ValueTask<TResult> right) { return left.Equals(right); } public static bool operator !=(ValueTask<TResult> left, ValueTask<TResult> right) { return !left.Equals(right); } public Task<TResult> AsTask() { object obj = _obj; if (obj == null) return Task.FromResult<TResult>(_result); Task<TResult> task = obj as Task<TResult>; if (task != null) return task; return GetTaskForValueTaskSource(Unsafe.As<IValueTaskSource<TResult>>(obj)); } public ValueTask<TResult> Preserve() { if (_obj != null) return new ValueTask<TResult>(AsTask()); return this; } private Task<TResult> GetTaskForValueTaskSource(IValueTaskSource<TResult> t) { ValueTaskSourceStatus status = t.GetStatus(_token); if (status != 0) try { return Task.FromResult<TResult>(t.GetResult(_token)); } catch (Exception exception) { if (status != ValueTaskSourceStatus.Canceled) { TaskCompletionSource<TResult> taskCompletionSource = new TaskCompletionSource<TResult>(); taskCompletionSource.TrySetException(exception); return taskCompletionSource.Task; } Task<TResult> task = s_canceledTask; if (task == null) { TaskCompletionSource<TResult> taskCompletionSource2 = new TaskCompletionSource<TResult>(); taskCompletionSource2.TrySetCanceled(); task = (s_canceledTask = taskCompletionSource2.Task); } return task; } ValueTaskSourceAsTask valueTaskSourceAsTask = new ValueTaskSourceAsTask(t, _token); return valueTaskSourceAsTask.Task; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTaskAwaiter<TResult> GetAwaiter() { return new ValueTaskAwaiter<TResult>(this); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ConfiguredValueTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext) { return new ConfiguredValueTaskAwaitable<TResult>(new ValueTask<TResult>(_obj, _result, _token, continueOnCapturedContext)); } public override string ToString() { if (IsCompletedSuccessfully) { TResult result = Result; if (result != null) return result.ToString(); } return string.Empty; } } }