C#、事件处理程序和线程

标签 c# multithreading events worker-thread

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

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

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

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

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

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

最佳答案

有两种选择:

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

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

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);
    }
}

关于C#、事件处理程序和线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1067532/

相关文章:

c# - AsNoTracking() 背后是否有任何隐藏功能?

java - 线程名称和两次调用run方法

javascript - onfullscreenchange DOM 事件

javascript - 为什么 Event Object 中存在细微的跨浏览器差异

c# - 标准网络服务 (asmx) 是否与 MVC 一起工作?

C#tcpclient程序写入流但客户端未接收数据

c# - 生成的 WCF 代理配置使用服务器的本地名称

multithreading - 在 akka scala Actor 中使用单例

c# - 为什么线程创建这么快?

jquery - MooTools 中的事件绑定(bind)(如 jQuery)