继承自DispatcherObject

时间:2011-12-02 17:56:26

标签: .net wpf multithreading

我想创建一个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应用程序。)

3 个答案:

答案 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中没有可能抽取信息。