1

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

背后的代码是

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 个消息框。

同时,跟踪显示Button ThreadIdInvoked ThreadId的数字相同。

4

3 回答 3

2

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

于 2009-07-31T17:07:48.030 回答
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.

PS 正如您在代码中看到的,委托还调用MessageBox.Show(). 这会导致一个新的消息框,它与前一个消息框是模态的。我注意到我不能在“调用”之前单击“直接”消息框上的“确定”。

于 2009-07-31T22:32:25.503 回答
0

我是这个 WPF Dispatcher 的新手,所以如果我完全错了,请给我投反对票,但看起来你对this.Dispatcher的调用实际上是你的窗口(UI 线程)调度程序。因此,任何代码都将由 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 上发现了这篇文章,它真正阐明了有关 WPF 线程/调度程序模型的事情。

于 2009-07-31T17:08:09.137 回答