c# - 来自不同线程的触发事件

标签 c# wpf

在我的主窗口(线程 A)中,我启动了一个新线程(线程 B),该线程在用户等待时执行一些工作。

如果出现错误或需要用户提供额外信息,线程 B 会触发事件,线程 A 将监听这些事件。

在线程 A 的事件监听器中,我需要向用户显示对话框消息,我有一个自定义对话框窗口并使用 dialogWindow.showDialog() 显示它。这工作正常,但是当我尝试设置对话框的所有者时会导致错误,我这样做 dialogWindow.Owner = Window.GetWindow(this)

我得到的错误是:调用线程无法访问此对象,因为另一个线程拥有它。

监听从不同线程触发的事件的正确方法是什么?

最佳答案

事件监听器代码将在触发事件的线程中隐式运行,因此事件监听器不是线程绑定(bind)的。

如果您想在 UI 中显示一些事件处理的结果,您应该自己进行编码。类似的东西:

void OnEvent(object sender, EventArgs args)
{
    // runs in the event sender's thread
    string x = ComputeChanges(args);
    Dispatcher.BeginInvoke((Action)(
        () => UpdateUI(x)
    ));
}

void UpdateUI(string x)
{
    // runs in the UI thread
    control.Content = x;
    // - or -
    new DialogWindow() { Content = x, Owner = this }.ShowDialog();
    // - or whatever
}

因此:您最好在后台线程中执行您的计算(如果有的话),而无需触及 UI;之后,当您知道 UI 中需要更改哪些内容时,您可以在 UI 线程中执行 UI 更新代码。

Dispatcher 是控件的一个属性,因此如果您的代码是 UI 的一部分,您将免费获得 Dispatcher。否则,您可以从任何控件中获取调度程序(例如,control.Dispatcher)。

关于c# - 来自不同线程的触发事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10315370/

相关文章:

wpf - 如何在 WPF 中设置窗口的边框和标题栏的样式?

c# - 根据通用类型参数查询不同的列

c# - 使用 X509 证书从 XML 文件中提取公钥?

c# - MYSQL 空值干扰 C# 应用程序

wpf - WPF 应用程序可以进行依赖注入(inject)吗?

wpf - 如何将 "Red"这样的字符串转换为 System.Windows.Media.Color?

c# - 是否有一种简单的方法来导航 List<t> 对象?

c# - 如何确定程序集名称是否与请求的部分程序集名称匹配

c# - C# WPF 中嵌套数据绑定(bind)与 ItemsControl 的对齐

c# - 如何使用 json.net 反序列化派生类