【问题标题】:Fire events from different thread来自不同线程的触发事件
【发布时间】:2012-04-25 12:13:53
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    事件侦听器代码将隐式运行在触发事件的线程上,因此事件侦听器不是线程绑定的。

    如果您想在 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)。

    【讨论】:

      【解决方案2】:

      从后台线程向 UI 线程引发事件的正确方法是,应该在该 Dispatcher 上引发事件, 这里的关键是事先获取 UIthread 的调度器。

      UIDisaptcher.BeginInvoke((ThreadStart)(() => RaiseEventToUIThread()));

      当 UI 线程监听引发的事件时,它可以设置 Owner 属性(因为窗口是由 UI 线程创建的)。

      【讨论】:

      • 谢谢,效果很好。我使用的是 Invoke 而不是 BeginInvoke,但同样的事情。
      • 请使用 BeginInvoke 调用不会释放句柄。
      【解决方案3】:

      当然 -> 我们所做的是使用 SynchronizationContext。 因此,当您启动一个新线程时,您(在 UI 线程上)捕获当前上下文并将其作为参数传递给第二个线程。

      然后在第二个线程上,当你想引发一个事件时,你可以这样做:

          if (_uiThreadId != Thread.CurrentThread.ManagedThreadId)
          {
              _uiContext.Post(
                  new SendOrPostCallback(delegate(object o) { OnYourEvent((EventArgs)o); }),
                  e);
          }
          else
              OnYourEvent(e);
      

      【讨论】:

      • 多么好的解决方案啊!不知道同步上下文,很好的参考!竖起大拇指!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-30
      • 1970-01-01
      • 2016-11-01
      • 1970-01-01
      相关资源
      最近更新 更多