【问题标题】:How to call sibling objects from a foreign thread如何从外部线程调用兄弟对象
【发布时间】:2014-04-17 23:55:03
【问题描述】:

我有一个包含大量用户控件的 WPF 应用程序。其中一个控件还使用第三方 DLL,该 DLL 监视外部系统并产生事件。我订阅了这些事件并通过以下方式处理它们:

public class ControlClassD
{
    private 3rdPartyEventSource _3rdPartyEventSource = new 3rdPartyEventSource();

    public ControlClassD()
    {
        _3rdPartyEventSource.NewEvent += _3rdPartyEventSource_NewEvent;
        _3rdPartyEventSource.StartMakingEventsWhenSomethingHappens();
    }

    private void _3rdPartyEventSource_NewEvent(object o)
    {
        InstanceOfControlClassA.doSomethingWith(o);
        InstanceOfControlClassB.doSomethingWith(o);
        InstanceOfControlClassC.doSomethingWith(o);
    }
}

所有 InstanceOfControlClassx 都由启动时在 MainWindow 类中运行 _Loaded 事件处理程序的任何线程实例化。

执行处理程序的线程是由 3rdPartyEventSource 创建的,无法访问所有这些东西(如该性质的错误消息所示)

我想做的是让 3rdPartyEventSource 传递的线程返回并让创建所有这些实例的线程 (CreatorThread) 执行 HandleNewEvent。喜欢:

    private void _3rdPartyEventSource_NewEvent(object o)
    {
        SomehowInvokeCreatorThread(new Action(() => HandleNewEvent(o)));
    }

    private void HandleNewEvent(object o)
    {
        InstanceOfControlClassA.doSomethingWith(o);
        InstanceOfControlClassB.doSomethingWith(o);
        InstanceOfControlClassC.doSomethingWith(o);  //which may access this
    }

我该怎么做?

【问题讨论】:

  • 你能做类似stackoverflow.com/questions/5868451/…的事情吗?
  • 我正在尝试在该线程的最后一个答案中做“矮胖”的事情,但我不知道在我的情况下“r”是什么。

标签: c# wpf multithreading


【解决方案1】:

有很多方法可以做到这一点,但以下一种可能是最简单的。只需创建您自己的包装事件,该事件将在 UI 线程上触发:

public class ControlClassD
{
    public class WrapperEventArgs: EventArgs { public object Arg { get; set; } }
    public event EventHandler<WrapperEventArgs> WrapperEvent = delegate { };

    private 3rdPartyEventSource _3rdPartyEventSource = new 3rdPartyEventSource();

    public ControlClassD()
    {
        var dispatcher = Dispatcher.CurrentDispatcher;

        _3rdPartyEventSource.NewEvent += obj =>
              dispatcher.BeginInvoke(new Action(() => 
                  this.WrapperEvent(this, new WrapperEventArgs { Arg = obj })));

        this.WrapperEvent += ControlClassD_WrapperEventHandler;

        _3rdPartyEventSource.StartMakingEventsWhenSomethingHappens();
    }

    private void ControlClassD_WrapperEventHandler(
        object sender, WrapperEventArgs args)
    {
        InstanceOfControlClassA.doSomethingWith(args.Arg);
        InstanceOfControlClassB.doSomethingWith(args.Arg);
        InstanceOfControlClassC.doSomethingWith(args.Arg);
    }
}

【讨论】:

  • 似乎很有趣...对我来说绝对是新的。我认为有一些错误吗?你能检查你的例子和我的改动吗? 1) 我将 WrapperEventArgs 的定义移到 ClassD 的定义之外。 2) WrapperEventHandler 的定义在 ClassD 内部或外部似乎无效,VS 表示它无法解析该符号。 WrapperEventHandler 应该在哪里/如何定义?
  • @davecove,是EventHandler&lt;WrapperEventArgs&gt;,我打错了。
  • @davecove,请记住 BeginInvoke 是异步的。也就是说,您的事件源可能会生成另一个NewEvent,而之前的WrapperEvent 仍在排队等待UI 线程上的处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-01
相关资源
最近更新 更多