8

我正在写一个小聊天应用程序,我有这个事件处理程序:

void o_Typing(object sender, EventArgs e)
{
    MessageBox.Show("Fired!");
    this.Text = "Fired!";
}

o_Typing是派生自 的类中的方法TabPage。基本上,我希望每个对话都有自己的标签。

事件处理程序由我的 Chat 对象触发,该对象在另一个线程中运行。我有 1 个用于 UI 的线程,以及用于每个聊天对话的另一个线程(以不断轮询服务器以获取新数据)

触发事件时,会MessageBox弹出,但选项卡标题不会更改。事件触发一次后,它就再也不会触发了,这让我相信该事件是在工作线程中调用的,尽管它是在 UI 线程中定义的。

如何让我的事件从工作线程中调用,并用于Invoke()让它们在 UI 线程上执行?

4

2 回答 2

10

有两种选择:

1) 使事件处理程序线程安全:Control.Invoke/BeginInvoke在任何需要与 UI 线程对话的事件处理程序中使用。

2)在引发事件之前让工作线程编组回UI线程 - 换句话说,Control.Invoke用作引发事件的过程的一部分,以便事件处理程序将全部在UI线程中调用。根据您的应用程序的结构,您可能不希望您的事件引发组件明确了解 UI - 但是当它正在构建时,您可以传入一个ISynchronizeInvokeControl实现)并且您的组件可以使用它来引发它的事件正确的线程。当然,只有在每个事件处理程序都乐于在同一个线程上运行时,这才有效(简单地说,无论如何)——但情况往往如此。你会写这样的东西:

protected void OnFoo(EventArgs args)
{
    if (sync != null && sync.InvokeRequired)
    {
        sync.Invoke((Action) delegate { OnFoo(args) }, null);
        return;
    }
    EventHandler handler = Foo; // Where Foo is the event name
    if (handler != null)
    {
        handler (this, args);
    }
}
于 2009-07-01T06:24:20.410 回答
5

如果您在工作线程执行的代码中触发事件,则订阅该事件的所有方法都将在该工作线程下执行。

对于 GUI 元素,您需要查看调用方法。

最好的祝福

于 2009-07-01T06:18:50.310 回答