根据MSDN,Dispatcher
提供管理线程工作项队列的服务。
一个简单的问题。我想仅使用Dispatcher
:作为工作项的队列(通过Dispatcher.BeginInvoke
发布),我的后台线程将以连续方式提供。
我不想让这个线程成为一个STA线程,我不需要在它上面输入Windows消息。这个帖子上没有用户界面。
使用Dispatcher
是否合法?
答案 0 :(得分:4)
这是使用Dispatcher的合法方式吗?
你可以 use a secondary thread with a Dispatcher
,但这种情况并不常见。通常这样做是为了使UI的不同部分在不同的UI线程上运行。调度程序线程将处理Windows消息,并且必须是STA。另外,从技术上讲,处理不是严格的FIFO,因为调度的项目优先排队。
尽管如此,即使它没有设计为在没有用户界面的情况下使用,你也可以以这种方式使用它。
备选方案:
1)AsyncContextThread
是一个带有AsyncEx NuGet库工作队列的简单线程:
private readonly AsyncContextThread _thread = new AsyncContextThread();
...
_thread.Factory.StartNew(() => { ... });
AsyncContextThread
类型为其运行的代码提供SynchronizationContext
,因此默认情况下async
个连续将在同一个线程上恢复。
2)如果只是串行处理请求并且实际上并不重要他们运行的线程,那么您可以使用任务scheduler指示线程池一次运行一个请求,如下所示:
private readonly TaskFactory _factory = new TaskFactory(
new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler);
_factory.StartNew(() => { ... });
答案 1 :(得分:3)
如果您需要实际使用Dispatcher
运行时组件,例如System.Windows.Media.Imaging,那么我有一个答案。如果您没有使用Dispatcher
运行时组件,那么甚至不要考虑使用Dispatcher
运行时。请改用任务并行库(TPL)。
我在大批量制作服务中构建并使用this DispatcherTaskScheduler
implementation。您可以使用尽可能多的线程来配置它以拥有一个池(默认为核心数),它将负责启动这些线程,使用Dispatcher
运行时初始化它们然后排队并向他们派遣工作。适用于TPL,TPL DataFlow,SynchronizationContext
样式编程(例如异步/等待)等。
基本用法如下所示:
Task.Factory.StartNew(() =>
{
// Do anything you want with Dispatcher components here
},
CancellationToken.None,
TaskCreationOptions.None,
DispatcherTaskFactory.Default);
如果您配置自己的实例(例如,您需要更多线程),那么只需将DispatcherTaskFactory.Default
替换为您的实例。我的建议是不要配置比核心更多的线程(只使用Default
实例),并确保你只尝试在这些线程上进行Dispatcher
运行时工作。
正如我所提到的,我在与图像处理相关的软件系统的几个部分中使用了这个实现,这些部分是我们业务的核心,并且承受了大量的负载,并且它已经证明对我们来说绝对是防弹。
最后,免责声明:Microsoft并不真正支持像这样使用的Dispatcher
运行时。