e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
204 lines
6.1 KiB
C#
204 lines
6.1 KiB
C#
// <copyright>
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
|
|
namespace System.Runtime
|
|
{
|
|
using System.Runtime.CompilerServices;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
internal static class TaskExtensions
|
|
{
|
|
public static IAsyncResult AsAsyncResult<T>(this Task<T> task, AsyncCallback callback, object state)
|
|
{
|
|
if (task == null)
|
|
{
|
|
throw Fx.Exception.ArgumentNull("task");
|
|
}
|
|
|
|
if (task.Status == TaskStatus.Created)
|
|
{
|
|
throw Fx.Exception.AsError(new InvalidOperationException(InternalSR.SFxTaskNotStarted));
|
|
}
|
|
|
|
var tcs = new TaskCompletionSource<T>(state);
|
|
|
|
task.ContinueWith(
|
|
t =>
|
|
{
|
|
if (t.IsFaulted)
|
|
{
|
|
tcs.TrySetException(t.Exception.InnerExceptions);
|
|
}
|
|
else if (t.IsCanceled)
|
|
{
|
|
// the use of Task.ContinueWith(,TaskContinuationOptions.OnlyOnRanToCompletion)
|
|
// can give us a cancelled Task here with no t.Exception.
|
|
tcs.TrySetCanceled();
|
|
}
|
|
else
|
|
{
|
|
tcs.TrySetResult(t.Result);
|
|
}
|
|
|
|
if (callback != null)
|
|
{
|
|
callback(tcs.Task);
|
|
}
|
|
},
|
|
TaskContinuationOptions.ExecuteSynchronously);
|
|
|
|
return tcs.Task;
|
|
}
|
|
|
|
public static IAsyncResult AsAsyncResult(this Task task, AsyncCallback callback, object state)
|
|
{
|
|
if (task == null)
|
|
{
|
|
throw Fx.Exception.ArgumentNull("task");
|
|
}
|
|
|
|
if (task.Status == TaskStatus.Created)
|
|
{
|
|
throw Fx.Exception.AsError(new InvalidOperationException(InternalSR.SFxTaskNotStarted));
|
|
}
|
|
|
|
var tcs = new TaskCompletionSource<object>(state);
|
|
|
|
task.ContinueWith(
|
|
t =>
|
|
{
|
|
if (t.IsFaulted)
|
|
{
|
|
tcs.TrySetException(t.Exception.InnerExceptions);
|
|
}
|
|
else if (t.IsCanceled)
|
|
{
|
|
// the use of Task.ContinueWith(,TaskContinuationOptions.OnlyOnRanToCompletion)
|
|
// can give us a cancelled Task here with no t.Exception.
|
|
tcs.TrySetCanceled();
|
|
}
|
|
else
|
|
{
|
|
tcs.TrySetResult(null);
|
|
}
|
|
|
|
if (callback != null)
|
|
{
|
|
callback(tcs.Task);
|
|
}
|
|
},
|
|
TaskContinuationOptions.ExecuteSynchronously);
|
|
|
|
return tcs.Task;
|
|
}
|
|
|
|
public static ConfiguredTaskAwaitable SuppressContextFlow(this Task task)
|
|
{
|
|
return task.ConfigureAwait(false);
|
|
}
|
|
|
|
public static ConfiguredTaskAwaitable<T> SuppressContextFlow<T>(this Task<T> task)
|
|
{
|
|
return task.ConfigureAwait(false);
|
|
}
|
|
|
|
public static ConfiguredTaskAwaitable ContinueOnCapturedContextFlow(this Task task)
|
|
{
|
|
return task.ConfigureAwait(true);
|
|
}
|
|
|
|
public static ConfiguredTaskAwaitable<T> ContinueOnCapturedContextFlow<T>(this Task<T> task)
|
|
{
|
|
return task.ConfigureAwait(true);
|
|
}
|
|
|
|
public static void Wait<TException>(this Task task)
|
|
{
|
|
try
|
|
{
|
|
task.Wait();
|
|
}
|
|
catch (AggregateException ex)
|
|
{
|
|
throw Fx.Exception.AsError<TException>(ex);
|
|
}
|
|
}
|
|
|
|
public static bool Wait<TException>(this Task task, int millisecondsTimeout)
|
|
{
|
|
try
|
|
{
|
|
return task.Wait(millisecondsTimeout);
|
|
}
|
|
catch (AggregateException ex)
|
|
{
|
|
throw Fx.Exception.AsError<TException>(ex);
|
|
}
|
|
}
|
|
|
|
public static bool Wait<TException>(this Task task, TimeSpan timeout)
|
|
{
|
|
try
|
|
{
|
|
if (timeout == TimeSpan.MaxValue)
|
|
{
|
|
return task.Wait(Timeout.Infinite);
|
|
}
|
|
else
|
|
{
|
|
return task.Wait(timeout);
|
|
}
|
|
}
|
|
catch (AggregateException ex)
|
|
{
|
|
throw Fx.Exception.AsError<TException>(ex);
|
|
}
|
|
}
|
|
|
|
public static void Wait(this Task task, TimeSpan timeout, Action<Exception, TimeSpan, string> exceptionConverter, string operationType)
|
|
{
|
|
bool timedOut = false;
|
|
|
|
try
|
|
{
|
|
if (timeout > TimeoutHelper.MaxWait)
|
|
{
|
|
task.Wait();
|
|
}
|
|
else
|
|
{
|
|
timedOut = !task.Wait(timeout);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (Fx.IsFatal(ex) || exceptionConverter == null)
|
|
{
|
|
throw;
|
|
}
|
|
|
|
exceptionConverter(ex, timeout, operationType);
|
|
}
|
|
|
|
if (timedOut)
|
|
{
|
|
throw Fx.Exception.AsError(new TimeoutException(InternalSR.TaskTimedOutError(timeout)));
|
|
}
|
|
}
|
|
|
|
public static Task<TBase> Upcast<TDerived, TBase>(this Task<TDerived> task) where TDerived : TBase
|
|
{
|
|
return (task.Status == TaskStatus.RanToCompletion) ?
|
|
Task.FromResult((TBase)task.Result) :
|
|
UpcastPrivate<TDerived, TBase>(task);
|
|
}
|
|
|
|
private static async Task<TBase> UpcastPrivate<TDerived, TBase>(this Task<TDerived> task) where TDerived : TBase
|
|
{
|
|
return await task.ConfigureAwait(false);
|
|
}
|
|
}
|
|
}
|