我想创建一个DispatcherObject
的子类来创建我自己的带有消息队列的线程关联对象,就像WPF用于UI元素一样。
我有一个测试应用程序在没有崩溃的情况下运行,但是DispatcherObject似乎没有处理它的消息队列。我刚刚创建了一个新的空白WPF应用程序,并将此代码添加到MainWindow.xaml.cs
:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
DispatcherWorker worker = null;
ManualResetEventSlim latch = new ManualResetEventSlim(false);
new Thread(() => {
worker = new DispatcherWorker();
latch.Set();
}).Start();
latch.Wait();
// worker.Dispatcher.Thread is stopped by here... why?
worker.Dispatcher.BeginInvoke(new Action(() => {
// This code never executed
worker.DoWork(this);
}));
}
}
public class DispatcherWorker : DispatcherObject {
public void DoWork(MainWindow window) {
VerifyAccess();
window.Dispatcher.BeginInvoke(new Action(() => window.Background = Brushes.Black));
}
}
永远不会执行DoWork()
方法,如果我在调用BeginInvoke
之前放置一个断点,我会看到Dispatcher的线程已停止。它为什么停止了?我设置线程错了吗?
(This similar question似乎有同样的问题,但接受的答案是在GUI应用程序中运行代码,这将有一个消息泵。但即使在运行时我也遇到了同样的问题GUI应用程序。)
答案 0 :(得分:3)
拥有Dispatcher
的线程需要" pump" Dispatcher
。也就是说,需要告诉它处理通过Dispatcher
排队的消息。为此,请使用DispatcherFrame
:
Dispatcher.PushFrame(new DispatcherFrame());
设置闩锁后应该出现这种情况。该线程永远不会退出 - 它只会在该线程的调度程序上发送消息。如果您希望它具有退出条件,请参阅DispatcherFrame
Continue
属性的文档。
请注意,无论您是使用自定义DispatcherWorker
类还是其他内置WPF类,都无关紧要。如果没有任何东西在该线程上引用Dispatcher
,则不会处理任何消息。
答案 1 :(得分:1)
我认为这是因为worker.Dispatcher
引用了创建DispatcherObject
(在本例中为DispatcherWorker
)的线程,该线程是在Thread
中创建的Stopped
构造函数。
由于该线程已经启动并完成了它的工作,因此当前状态为DoWork()
。您可能需要再次启动才能运行{{1}}
您可以找到有关主题here
的更多信息答案 2 :(得分:0)
确实,你已经创建了一个帖子。并且您的DispatcherWorker在创建的线程的范围内实例化,这使您创建DispatcherWorker的CurrentThread的线程成为可能。
因此,在BeginInvoke中会发生DispatcherWorker中止,因为PostMessage(“user32.dll”)不会从DispatcherWorker中提取消息。如果你的工作者在创建的线程范围之外被实例化,那么一切都会顺利进行,因为他的调度程序是主线程调度程序。
总而言之,你的工作者失败是因为在BeginInvoke中没有可能抽取信息。