/// <summary> /// Returns a <see cref="Task"/> that is canceled when this <see cref="CancellationToken"/> is canceled. This method will leak resources if the cancellation token is long-lived; use <see cref="ToCancellationTokenTaskSource"/> for a similar approach with proper resource management. /// </summary> /// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor.</param> /// <returns>A <see cref="Task"/> that is canceled when this <see cref="CancellationToken"/> is canceled.</returns> public static Task AsTask(this CancellationToken cancellationToken) { if (!cancellationToken.CanBeCanceled) { return TaskConstants.Never; } if (cancellationToken.IsCancellationRequested) { return TaskConstants.Canceled; } var tcs = new TaskCompletionSource(); cancellationToken.Register(() => tcs.TrySetCanceled(), false); return tcs.Task; }
/// <summary> /// Creates a task for the specified cancellation token, registering with the token if necessary. /// </summary> /// <param name="cancellationToken">The cancellation token to observe.</param> public CancellationTokenTaskSource(CancellationToken cancellationToken) { if (!cancellationToken.CanBeCanceled) { Task = TaskConstants.Never; return; } if (cancellationToken.IsCancellationRequested) { Task = TaskConstants.Canceled; return; } var tcs = new TaskCompletionSource(); _registration = cancellationToken.Register(() => tcs.TrySetCanceled(), false); Task = tcs.Task; }
private static AsyncCallback Callback(Action<IAsyncResult> endMethod, TaskCompletionSource<object> tcs) { return asyncResult => { try { endMethod(asyncResult); tcs.TrySetResult(null); } catch (OperationCanceledException) { tcs.TrySetCanceled(); } catch (Exception ex) { tcs.TrySetException(ex); } }; }