简体   繁体   English

非UI线程上的WPF Dispatcher

[英]WPF Dispatcher on non-UI thread

According to MSDN, Dispatcher provides services for managing the queue of work items for a thread. 根据MSDN, Dispatcher 提供了用于管理线程工作项队列的服务。

A simple question. 一个简单的问题。 I want to use Dispatcher just for that: as a queue of work items (posted via Dispatcher.BeginInvoke ) which my background thread will serve in a serial manner. 我想为此使用Dispatcher :作为工作项的队列(通过Dispatcher.BeginInvoke发布),我的后台线程将以串行方式提供。

I don't want to make this thread an STA thread and I don't need to pump Windows messages on it. 我不想将此线程设为STA线程,也不需要在其上注入Windows消息。 There will be no UI on this thread. 这个帖子上没有UI。

Is it a legitimate way of using Dispatcher ? 这是使用Dispatcher的合法方式吗?

Is it a legitimate way of using Dispatcher? 这是使用Dispatcher的合法方式吗?

You could use a secondary thread with a Dispatcher , but it's rather uncommon. 可以 将辅助线程与Dispatcher一起使用 ,但这种情况并不常见。 This is usually done so that different parts of the UI run on different UI threads. 通常这样做是为了使UI的不同部分在不同的UI线程上运行。 A dispatcher thread will process Windows messages, and must be STA. 调度程序线程将处理Windows消息,并且必须是STA。 Also, technically speaking the processing isn't strictly FIFO since dispatched items are queued with a priority. 同样,从技术上讲,处理并不是严格意义上的FIFO,因为已调度的项目将按优先级排队。

That said, even though it wasn't designed to be used without a UI, you could use it that way. 也就是说,即使不是没有UI也不打算使用它,您也可以那样使用它。

Alternatives: 备择方案:

1) AsyncContextThread is a simple thread with a work queue from my AsyncEx NuGet library: 1) AsyncContextThread是一个带有AsyncEx NuGet库工作队列的简单线程:

private readonly AsyncContextThread _thread = new AsyncContextThread();
...
_thread.Factory.StartNew(() => { ... });

The AsyncContextThread type provides a SynchronizationContext for the code it runs, so async continuations will resume on the same thread by default. AsyncContextThread类型为其运行的代码提供SynchronizationContext ,因此默认情况下async延续将在同一线程上恢复。

2) If it only matters that the requests are processed serially , and doesn't actually matter which thread they run on, then you can use a task scheduler to instruct the thread pool to run your requests one at a time, as such: 2)如果请求是按顺序处理的,并且实际上它们运行的​​是哪个线程并不重要,那么您可以使用任务调度程序来指示线程池一次运行一个请求,如下所示:

private readonly TaskFactory _factory = new TaskFactory(
    new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler);
_factory.StartNew(() => { ... });

Short answer: 简短回答:

If you need to actually do work with Dispatcher runtime components, such as System.Windows.Media.Imaging, then I have an answer for you. 如果您实际上需要使用Dispatcher运行时组件(例如System.Windows.Media.Imaging),那么我为您提供了一个答案。 If you're not using Dispatcher runtime components then don't even consider using the Dispatcher runtime. 如果您不使用Dispatcher运行时组件,那么甚至不要考虑使用Dispatcher运行时。 Use the Task Parallel Library (TPL) instead. 请改用任务并行库(TPL)。

Long answer: 答案很长:

I've built and use this DispatcherTaskScheduler implementation in high volume production services. 我已经在大量生产服务中构建并使用了DispatcherTaskScheduler实现 You can configure it with as many threads as you'd like it to have a pool of (default is number of cores) and it will take care of spinning up those threads, initializing them with the Dispatcher runtime and then queuing and dispatching work to them. 您可以使用尽可能多的线程配置它以拥有一个池(默认为核心数),它将负责启动这些线程,使用Dispatcher运行时初始化它们,然后排队并将工作分派到他们。 Works with great with TPL, TPL DataFlow, SynchronizationContext style programming (eg async/await), etc. 与TPL,TPL DataFlow, SynchronizationContext样式编程(例如async / await)等紧密配合使用。

Basic usage looks something like this: 基本用法如下所示:

Task.Factory.StartNew(() =>
{
   // Do anything you want with Dispatcher components here
},
CancellationToken.None,
TaskCreationOptions.None,
DispatcherTaskFactory.Default);

If you configure your own instance (eg you want more threads) then just replace DispatcherTaskFactory.Default with your instance instead. 如果您配置自己的实例(例如,您想要更多的线程),则只需将DispatcherTaskFactory.Default替换为您的实例。 My advice is to not configure more threads than cores (just use the Default instance) and make sure you try to only do Dispatcher runtime work on these threads. 我的建议是不要配置比内核更多的线程(仅使用Default实例),并确保您仅尝试在这些线程上执行Dispatcher运行时工作。

As I mentioned, I use this implementation in several parts of our software system related to image processing that are core to our business and endure high volume loads and it's proven absolutely bullet proof for us. 正如我提到的,我在与图像处理相关的软件系统的多个部分中使用了该实现,这些实现是我们业务的核心,并承受大量负载,并且事实证明,这对我们来说绝对是证明。

Finally, the disclaimer: Microsoft doesn't really support the Dispatcher runtime being used like this. 最后,免责声明:Microsoft并不真正支持像这样使用Dispatcher运行时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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