如何从外部线程调用同级对象

本文关键字:对象 调用 线程 从外部 | 更新日期: 2023-09-27 17:58:55

我有一个带有大量用户控件的WPF应用程序。其中一个控件还使用第三方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
    }

我该怎么做?

如何从外部线程调用同级对象

有很多方法可以做到这一点,但下面的方法可能是最简单的。只需创建您自己的包装器事件,该事件将在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);
    }
}