/// <summary> /// Creates a task for waiting the <see cref="System.Threading.WaitHandle"/>, so you can write: "if (await waitHandle.WaitOneAsync()) ... else ..." or "await waitHandle.WaitOneAsync().ContinueWith(...)" /// </summary> /// <param name="waitHandle">An instance of <see cref="System.Threading.AutoResetEvent"/>, <see cref="System.Threading.ManualResetEvent"/>, <see cref="System.Threading.Mutex"/>, or <see cref="System.Threading.Semaphore"/></param> /// <param name="timeoutMs">The wait timeout in milliseconds. Set to -1 to wait indefinitely. On timeout the awaiter throws <see cref="System.TimeoutException"/>.</param> /// <param name="cancellationToken">The cancellation token to stop waiting. If cancellation is requested, the Task will throw <see cref="System.OperationCanceledException"/>.</param> /// <returns>Returns a task which result tells if the <see cref="System.Threading.WaitHandle"/> signaled (True) or didn't (False), or throws the <see cref="System.OperationCanceledException"/></returns> public static Task <bool> WaitOneAsync(WaitHandle waitHandle, int timeoutMs, CancellationToken cancellationToken = default(CancellationToken)) { var tcs = new TaskCompletionSource <bool>(); var awaiter = waitHandle.ConfigureAwait(timeoutMs, cancellationToken).GetAwaiter(); Action completionAction = () => { if (awaiter.IsCanceled) { tcs.TrySetCanceled(); } else { tcs.TrySetResult(!awaiter.IsTimedOut); } }; awaiter.OnCompleted(completionAction); return(tcs.Task); }