解释奇怪的Dispatcher行为(隐藏的WPF功能)

时间:2009-07-31 16:57:07

标签: wpf dispatcher

我有一个窗口,里面有一个按钮。

代码隐藏是

private void Button_Click(object sender, RoutedEventArgs e)
{
    Trace.TraceInformation("Button ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);

    Thread w = new Thread((ThreadStart) Worker);
    w.SetApartmentState(ApartmentState.STA);  // removing/adding this doesn't make effect
    w.Start();
    MessageBox.Show("Direct");
}

void Worker()
{
    Trace.TraceInformation("Worker ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);

    this.Dispatcher.Invoke((Action)delegate
                               {
                                   Trace.TraceInformation("Invoked ThreadId: {0}", Thread.CurrentThread.ManagedThreadId);
                                   MessageBox.Show("Invoked");
                               });
}

点击该按钮会生成 2 消息框。

同时,trace为 Button ThreadId Invoked ThreadId 显示相同的数字。

3 个答案:

答案 0 :(得分:2)

Dispatcher始终在GUI线程上执行工作。这就是你的ThreadId匹配的原因。你问GUI线程 - “你的ThreadId是什么?”然后通过Dispatcher执行一些工作,Dispatcher再次进入GUI线程。

答案 1 :(得分:1)

散步后,我明白了发生了什么。

这是我的解释想法代码有什么问题(或问题发布的原因)。

Button_ClickDispatcher主题中执行。正如我所知,Dispatcher线程是一个窗口及其子窗口的单个线程。

即使Button_Click花费的时间超过一秒(足够长),并且用户设法再次点击该按钮(或以某种方式与UI交互),下一个Button_Click(或其他适当的处理程序)不会立即执行,而是放在调度队列中。

Dispatcher.Invoke在UI线程中执行委托。我想,Invoke会向委托GetMessage()循环发送一条消息并阻塞调用线程,直到消息完成。

我希望代表只有在退出 Button_Click后才能开始执行

MessageBox.Show()是一个阻止通话。在用户单击“确定”之前,不会执行下一个语句。

实际发生的事情是Dispatcher实际上区分了不同的窗口,并且知道Button_Click已经调用了一个模态对话框,因此与窗口的任何交互都应该发出一声嘟嘟声,并且消息框应该闪烁。

继续调度消息。毕竟,这就是为什么所有用户点击都被翻译成Button.Click消息并且消息框被关闭。

这就是在 Button_Click退出之前执行被调用的委托的原因。 被调用的代理分为 Button_Click

P.S。正如您在代码中看到的那样,代理人也会调用MessageBox.Show()。这会导致新的消息框与前一个消息框模态。我注意到在“调用”之前我无法在“直接”msgBox上单击“确定”。

答案 2 :(得分:0)

我是WPF Dispatcher的新手,所以如果我完全错了,请向我投票,但看起来你对 this.Dispatcher 的调用实际上是你的Window(UI线程)Dispatcher。因此,任何代码都将由UI线程执行,而不是您的应用程序实例化线程。

[编辑]

以下是我通过运行上述代码

收到的控制台输出
DispatcherQuestion.vshost.exe Information: 0 : Button ThreadId: 9    // UI Thread
DispatcherQuestion.vshost.exe Information: 0 : Worker ThreadId: 11   // Thread w
DispatcherQuestion.vshost.exe Information: 0 : Invoked ThreadId: 9   // UI Thread

ThreadID 9是用户界面线程。您的Button和您的Invoke调用都是由UI线程按设计执行的。

我在MSDN上发现了this article today,它确实澄清了WPF线程/调度程序模型的内容。