繁体   English   中英

非UI线程上的WPF Dispatcher

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM