既にこのコンテキストに投稿されているTask
を作成するにはどうすればいいですか(これは基本的には特定のスレッドのウィンドウです)SynchronizationContext
があるとします。特定のSynchronizationContextに投稿されるタスクを作成するにはどうすればよいですか?
参考のために、ここにはSynchronizationContext
の設定方法のデモンストレーション非常に基本的なのデモンストレーションがあります。
public class SomeDispatcher : SynchronizationContext
{
SomeDispatcher() {
new Thread(() => {
SynchronizationContext.SetSynchronizationContext(this);
// Dispatching loop (among other things)
}).Start();
}
override void Post(SendOrPostCallback d, object state)
{
// Add (d, state) to a dispatch queue;
}
}
非同期/がすでにコンテキストで実行されているを待っためにこれが正常に動作します。
ここでは、外部のコンテキスト(UIスレッドなど)からTask
をこれに投稿できるようにしたいが、これを行うためのきれいな方法を見つけることはできないようだ。
これを行う1つの方法は、TaskCompletionSource<>
を使用することです。
Task StartTask(Action action)
{
var tcs = new TaskCompletionSource<object>();
SaidDispatcher.Post(state => {
try
{
action.Invoke();
tcs.SetResult(null);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
});
return tcs.Task;
});
しかし、これはSynchronizationContext
からTaskFactory
インタフェースは、理想的には、おそらく
などホイールとバリエーションなどStartNew(Func<TResult>)
、StartNew(Func<Task<TResult>>)
を支える主要な痛みを、再発明されていますが、私は1つのインスタンスを作成するように見えることはできませんきれい:
TaskFactory CreateTaskFactory()
{
var original = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(SomeDispatcher); // yuck!
try
{
return new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
}
finally
{
SynchronizationContext.SetSynchronizationContext(original);
}
}
(。つまり、現在のスレッドの同期コンテキストはハックと思われる一時的なホースを有する)
既存のSynchronizationContextTaskSchedulerのロジックをコピーしてカスタムTaskSchedulerを実装するとどうなりますか?コピーは必須ではありませんが、ロジック自体は非常に単純です。 – Evk
@エヴァークあなたが使うことができない内部的なものがいくつかありますが、主なアイデアはまだあります。あなた自身の 'TaskScheduler'が必要です。 – Luaan
タスクを同期コンテキストに投稿する理由を教えてください。同期コンテキストの通常の使用は、同期コンテキストで開始されます。 –