public static async Task <bool> WaitOneAsync(this WaitHandle @this, int millisecondsTimeout, CancellationToken cancellationToken) { if (@this.GetType() == typeof(Mutex)) { throw new Exception("Async extensions do not work with mutex"); } RegisteredWaitHandle registeredHandle = null; CancellationTokenRegistration tokenRegistration = default; try { var tcs = new TaskCompletionSource <bool>(); registeredHandle = ThreadPool.RegisterWaitForSingleObject( @this, (state, timedOut) => ((TaskCompletionSource <bool>)state).TrySetResult(!timedOut), tcs, millisecondsTimeout, true); tokenRegistration = cancellationToken.Register( state => ((TaskCompletionSource <bool>)state).TrySetCanceled(), tcs); return(await tcs.Task); } finally { if (registeredHandle != null) { registeredHandle.Unregister(null); } tokenRegistration.Dispose(); } }