鑑於我已經擁有的SynchronizationContext
(並且基本上是特定主題的窗口),我如何創建發佈到此上下文的Task
?如何創建發佈到給定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
s,但似乎無法找到乾淨的方式來做到這一點。
一種方法是使用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;
});
但這是重新發明輪子和一個重大的痛苦支持的變化,如StartNew(Func<TResult>)
,StartNew(Func<Task<TResult>>)
等
一個TaskFactory
接口的SynchronizationContext
可能是最好的,但我似乎無法實例化一個清潔:
TaskFactory CreateTaskFactory()
{
var original = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(SomeDispatcher); // yuck!
try
{
return new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
}
finally
{
SynchronizationContext.SetSynchronizationContext(original);
}
}
(即具有臨時軟管當前線程的同步上下文似乎哈克。)
通過複製現有的SynchronizationContextTaskScheduler的邏輯來實現自定義的TaskScheduler怎麼樣?當然不需要複製,邏輯本身看起來很簡單。 – Evk
@Evk有幾個'internal's你不能使用,但主要想法仍然存在 - 你需要你自己的'TaskScheduler'。 – Luaan
爲什麼要將任務發佈到同步上下文?同步上下文的通常使用在同步上下文中開始。 –