/// <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"/>, 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>
 /// <exception cref="System.OperationCanceledException">Throws <see cref="System.OperationCanceledException"/> if the cancellation was requested using given <paramref name="cancellationToken"/></exception>
 public static Task <bool> WaitOneAsync(this WaitHandle waitHandle, int timeoutMs, CancellationToken cancellationToken = default(CancellationToken)) => WaitHandleAsyncOperations.WaitOneAsync(waitHandle, timeoutMs, cancellationToken);
 public static Task <bool> WaitAllAsync(this IEnumerable <WaitHandle> waitHandles, int timeoutMs, CancellationToken cancellationToken = default(CancellationToken)) => WaitHandleAsyncOperations.WaitAllAsync(waitHandles, timeoutMs, cancellationToken);