| File: Shared\Utilities\AsyncHelper.cs | Web Access |
| Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Threading; using System.Threading.Tasks; namespace Microsoft.Tools.ServiceModel.Svcutil { /// <summary> /// This class allows for running and cancelling a sync operation that is not cancellable. /// </summary> internal static class AsyncHelper { public static async Task RunAsync(Action action, CancellationToken cancellationToken) { await RunAsync(action, null, cancellationToken).ConfigureAwait(false); } public static async Task RunAsync(Action action, Action onCancellation, CancellationToken cancellationToken) { var taskCompletionSrc = new TaskCompletionSource<bool>(); using (cancellationToken.Register(() => taskCompletionSrc.SetCanceled())) { var actionTask = Task.Run(action, cancellationToken); await Task.WhenAny(actionTask, taskCompletionSrc.Task); } if (cancellationToken.IsCancellationRequested) { onCancellation?.Invoke(); } cancellationToken.ThrowIfCancellationRequested(); } public static async Task<T> RunAsync<T>(Func<T> func, CancellationToken cancellationToken) { return await RunAsync(func, null, cancellationToken).ConfigureAwait(false); } public static async Task<T> RunAsync<T>(Func<T> func, Action onCancellation, CancellationToken cancellationToken) { Task<T> finishedTask = null; var taskCompletionSrc = new TaskCompletionSource<T>(); using (cancellationToken.Register(() => taskCompletionSrc.SetCanceled())) { finishedTask = await Task.WhenAny(Task<T>.Run(func, cancellationToken), taskCompletionSrc.Task); } if (cancellationToken.IsCancellationRequested) { onCancellation?.Invoke(); } cancellationToken.ThrowIfCancellationRequested(); System.Diagnostics.Debug.Assert(finishedTask != taskCompletionSrc.Task, "Unexpected completion task!"); if (finishedTask == taskCompletionSrc.Task) { // this should never happen but if we introduce a bug here better fail earlier! throw new InvalidOperationException(); } return finishedTask.Result; } } }