[英]WPF Dispatcher on non-UI thread
根據MSDN, Dispatcher
提供了用於管理線程工作項隊列的服務。
一個簡單的問題。 我想為此使用Dispatcher
:作為工作項的隊列(通過Dispatcher.BeginInvoke
發布),我的后台線程將以串行方式提供。
我不想將此線程設為STA線程,也不需要在其上注入Windows消息。 這個帖子上沒有UI。
這是使用Dispatcher
的合法方式嗎?
這是使用Dispatcher的合法方式嗎?
您可以 將輔助線程與Dispatcher
一起使用 ,但這種情況並不常見。 通常這樣做是為了使UI的不同部分在不同的UI線程上運行。 調度程序線程將處理Windows消息,並且必須是STA。 同樣,從技術上講,處理並不是嚴格意義上的FIFO,因為已調度的項目將按優先級排隊。
也就是說,即使不是沒有UI也不打算使用它,您也可以那樣使用它。
備擇方案:
1) AsyncContextThread
是一個帶有AsyncEx NuGet庫工作隊列的簡單線程:
private readonly AsyncContextThread _thread = new AsyncContextThread();
...
_thread.Factory.StartNew(() => { ... });
AsyncContextThread
類型為其運行的代碼提供SynchronizationContext
,因此默認情況下async
延續將在同一線程上恢復。
2)如果請求是按順序處理的,並且實際上它們運行的是哪個線程並不重要,那么您可以使用任務調度程序來指示線程池一次運行一個請求,如下所示:
private readonly TaskFactory _factory = new TaskFactory(
new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler);
_factory.StartNew(() => { ... });
如果您實際上需要使用Dispatcher
運行時組件(例如System.Windows.Media.Imaging),那么我為您提供了一個答案。 如果您不使用Dispatcher
運行時組件,那么甚至不要考慮使用Dispatcher
運行時。 請改用任務並行庫(TPL)。
我已經在大量生產服務中構建並使用了此DispatcherTaskScheduler
實現 。 您可以使用盡可能多的線程配置它以擁有一個池(默認為核心數),它將負責啟動這些線程,使用Dispatcher
運行時初始化它們,然后排隊並將工作分派到他們。 與TPL,TPL DataFlow, SynchronizationContext
樣式編程(例如async / await)等緊密配合使用。
基本用法如下所示:
Task.Factory.StartNew(() =>
{
// Do anything you want with Dispatcher components here
},
CancellationToken.None,
TaskCreationOptions.None,
DispatcherTaskFactory.Default);
如果您配置自己的實例(例如,您想要更多的線程),則只需將DispatcherTaskFactory.Default
替換為您的實例。 我的建議是不要配置比內核更多的線程(僅使用Default
實例),並確保您僅嘗試在這些線程上執行Dispatcher
運行時工作。
正如我提到的,我在與圖像處理相關的軟件系統的多個部分中使用了該實現,這些實現是我們業務的核心,並承受大量負載,並且事實證明,這對我們來說絕對是證明。
最后,免責聲明:Microsoft並不真正支持像這樣使用Dispatcher
運行時。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.