// // Copyright (c) Microsoft Corporation. All rights reserved. // namespace System.Runtime { using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; internal static class TaskExtensions { 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(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(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 SuppressContextFlow(this Task task) { return task.ConfigureAwait(false); } public static ConfiguredTaskAwaitable ContinueOnCapturedContextFlow(this Task task) { return task.ConfigureAwait(true); } public static ConfiguredTaskAwaitable ContinueOnCapturedContextFlow(this Task task) { return task.ConfigureAwait(true); } public static void Wait(this Task task) { try { task.Wait(); } catch (AggregateException ex) { throw Fx.Exception.AsError(ex); } } public static bool Wait(this Task task, int millisecondsTimeout) { try { return task.Wait(millisecondsTimeout); } catch (AggregateException ex) { throw Fx.Exception.AsError(ex); } } public static bool Wait(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(ex); } } public static void Wait(this Task task, TimeSpan timeout, Action 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 Upcast(this Task task) where TDerived : TBase { return (task.Status == TaskStatus.RanToCompletion) ? Task.FromResult((TBase)task.Result) : UpcastPrivate(task); } private static async Task UpcastPrivate(this Task task) where TDerived : TBase { return await task.ConfigureAwait(false); } } }