Skip to content

Instantly share code, notes, and snippets.

@kekyo
Created August 29, 2017 00:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kekyo/3f1e58766bd6f1273d725509f54f0fd3 to your computer and use it in GitHub Desktop.
Save kekyo/3f1e58766bd6f1273d725509f54f0fd3 to your computer and use it in GitHub Desktop.
Task implementation by WaitHandle.
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace WaitHandleTasks
{
public static class WaitHandleExtension
{
public static Task AsTask(this WaitHandle waitHandle)
{
return waitHandle.AsTask(CancellationToken.None);
}
public static Task AsTask(this WaitHandle waitHandle, CancellationToken token)
{
var tcs = new TaskCompletionSource<object>();
var rwh = ThreadPool.RegisterWaitForSingleObject(
waitHandle,
(state, _) => ((TaskCompletionSource<object>)state).SetResult(null),
tcs,
int.MaxValue,
true);
token.Register(state =>
{
var t = (Tuple<RegisteredWaitHandle, WaitHandle, TaskCompletionSource<object>>)state;
t.Item1.Unregister(t.Item2);
tcs.SetCanceled();
},
Tuple.Create(rwh, waitHandle, tcs));
return tcs.Task;
}
}
class Program
{
static async Task ExecuteAsync(Func<Task> targetAsync)
{
var sw = new Stopwatch();
sw.Start();
await targetAsync();
sw.Stop();
Console.WriteLine("Elapsed: {0}", sw.Elapsed);
}
static async Task<int> MainAsync(string[] args)
{
await ExecuteAsync(async () =>
{
var targetWaitHandle1 = new ManualResetEvent(false);
Task.Run(() =>
{
Thread.Sleep(2000);
targetWaitHandle1.Set();
});
await targetWaitHandle1.AsTask();
});
await ExecuteAsync(async () =>
{
var targetWaitHandle1 = new ManualResetEvent(false);
var targetWaitHandle2 = new ManualResetEvent(false);
Task.Run(() =>
{
Thread.Sleep(3000);
targetWaitHandle1.Set();
});
Task.Run(() =>
{
Thread.Sleep(2000);
targetWaitHandle2.Set();
});
await Task.WhenAll(targetWaitHandle1.AsTask(), targetWaitHandle2.AsTask());
});
await ExecuteAsync(async () =>
{
var targetWaitHandle1 = new ManualResetEvent(false);
var cts = new CancellationTokenSource();
Task.Run(() =>
{
Thread.Sleep(2000);
cts.Cancel();
});
try
{
await targetWaitHandle1.AsTask(cts.Token);
throw new InvalidOperationException();
}
catch (OperationCanceledException)
{
}
});
return 0;
}
static int Main(string[] args)
{
return MainAsync(args).Result;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment