using System; using System.Threading.Tasks; namespace Unity.Services.Core { /// /// Set of utility functions added as extensions to /// and . /// static class AsyncOperationExtensions { /// /// Get a default awaiter on . /// /// /// The operation to create an awaiter for. /// /// /// Return a default awaiter for . /// /// /// This is required so we can directly use the /// keyword on an . /// public static AsyncOperationAwaiter GetAwaiter(this IAsyncOperation self) { return new AsyncOperationAwaiter(self); } /// /// Get a Task based on . /// /// /// The operation to create a Task for. /// /// /// Return a . /// public static Task AsTask(this IAsyncOperation self) { if (self.Status == AsyncOperationStatus.Succeeded) { return Task.CompletedTask; } var taskCompletionSource = new TaskCompletionSource(); void CompleteTask(IAsyncOperation operation) { switch (operation.Status) { case AsyncOperationStatus.Failed: taskCompletionSource.TrySetException(operation.Exception); break; case AsyncOperationStatus.Cancelled: taskCompletionSource.TrySetCanceled(); break; case AsyncOperationStatus.Succeeded: taskCompletionSource.TrySetResult(null); break; default: throw new ArgumentOutOfRangeException(); } } if (self.IsDone) { CompleteTask(self); } else { self.Completed += CompleteTask; } return taskCompletionSource.Task; } /// /// Get a default awaiter for . /// /// /// The operation to create an awaiter for. /// /// /// The result's type of . /// /// /// Return a default awaiter for . /// /// /// This is required so we can directly use the /// keyword on an . /// public static AsyncOperationAwaiter GetAwaiter(this IAsyncOperation self) { return new AsyncOperationAwaiter(self); } /// /// Get a Task based on . /// /// /// The operation to create a Task for. /// /// /// The result's type of . /// /// /// Return a /// public static Task AsTask(this IAsyncOperation self) { var taskCompletionSource = new TaskCompletionSource(); void CompleteTask(IAsyncOperation operation) { switch (operation.Status) { case AsyncOperationStatus.Succeeded: taskCompletionSource.TrySetResult(operation.Result); break; case AsyncOperationStatus.Failed: taskCompletionSource.TrySetException(operation.Exception); break; case AsyncOperationStatus.Cancelled: taskCompletionSource.TrySetCanceled(); break; default: throw new ArgumentOutOfRangeException(); } } if (self.IsDone) { CompleteTask(self); } else { self.Completed += CompleteTask; } return taskCompletionSource.Task; } } }