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