TaskToAsyncResult
Provides methods for using Task to implement the Asynchronous Programming Model
pattern based on "Begin" and "End" methods.
using System.Runtime.CompilerServices;
namespace System.Threading.Tasks
{
internal static class TaskToAsyncResult
{
private sealed class TaskAsyncResult : IAsyncResult
{
internal readonly Task _task;
[System.Runtime.CompilerServices.Nullable(2)]
private readonly AsyncCallback _callback;
[System.Runtime.CompilerServices.Nullable(2)]
[field: System.Runtime.CompilerServices.Nullable(2)]
public object AsyncState {
[System.Runtime.CompilerServices.NullableContext(2)]
get;
}
public bool CompletedSynchronously { get; }
public bool IsCompleted => _task.IsCompleted;
public WaitHandle AsyncWaitHandle => ((IAsyncResult)_task).AsyncWaitHandle;
[System.Runtime.CompilerServices.NullableContext(2)]
internal TaskAsyncResult([System.Runtime.CompilerServices.Nullable(0)] Task task, object state, AsyncCallback callback)
{
_task = task;
AsyncState = state;
if (task.IsCompleted) {
CompletedSynchronously = true;
callback?.Invoke(this);
} else if (callback != null) {
_callback = callback;
_task.ConfigureAwait(false).GetAwaiter().OnCompleted(delegate {
_callback(this);
});
}
}
}
public static IAsyncResult Begin(Task task, [System.Runtime.CompilerServices.Nullable(2)] AsyncCallback callback, [System.Runtime.CompilerServices.Nullable(2)] object state)
{
if (task == null)
throw new ArgumentNullException("task");
return new TaskAsyncResult(task, state, callback);
}
public static void End(IAsyncResult asyncResult)
{
Unwrap(asyncResult).GetAwaiter().GetResult();
}
public static TResult End<TResult>(IAsyncResult asyncResult)
{
return Unwrap<TResult>(asyncResult).GetAwaiter().GetResult();
}
public static Task Unwrap(IAsyncResult asyncResult)
{
if (asyncResult == null)
throw new ArgumentNullException("asyncResult");
Task obj = (asyncResult as TaskAsyncResult)?._task;
if (obj == null)
throw new ArgumentException(null, "asyncResult");
return obj;
}
public static Task<TResult> Unwrap<TResult>(IAsyncResult asyncResult)
{
if (asyncResult == null)
throw new ArgumentNullException("asyncResult");
Task<TResult> obj = (asyncResult as TaskAsyncResult)?._task as Task<TResult>;
if (obj == null)
throw new ArgumentException(null, "asyncResult");
return obj;
}
}
}