独自SynchronizationContextの実装
独自のスレッドでasync/awaitしたかったので、SynchronizationContextを実装する。
class SingleThreadSynchronizationContext : SynchronizationContext { BlockingCollection<Action> queue = new BlockingCollection<Action>(); Thread thread; public SingleThreadSynchronizationContext() { thread = new Thread(Run); thread.Start(); } void Run() { SynchronizationContext.SetSynchronizationContext(this); try { while (true) { var action = queue.Take(); action(); } } catch (InvalidOperationException) { // Complete } } public void Stop() { queue.CompleteAdding(); thread.Join(); } Task Exec(Action func) { var task = new TaskCompletionSource<object>(); queue.Add(() => { try { func(); task.SetResult(null); } catch (Exception e) { task.SetException(e); } }); return task.Task; } public override void Post(SendOrPostCallback d, object state) { Exec(() => d(state)); } public override void Send(SendOrPostCallback d, object state) { Exec(() => d(state)).Wait(); } public override SynchronizationContext CreateCopy() { return this; } }
こんな感じでasync/awaitが動作した。
Post、Send、CreateCopyあたりをオーバーライドすれば良いらしい。