如何在UI线程中创建一个eventlistener来侦听从第一个线程开始的另一个UI线程中的事件?

时间:2017-01-11 12:20:25

标签: c# wpf multithreading events

我试图寻找这个问题的解决方案已经有一段时间了,但我找不到任何解决方案。

我在单个实例应用程序中有两个UI线程,即窗口A和窗口B,其中创建了B并从A开始。当我尝试在A中添加一个事件监听器来监听B是否可见时,我在System.Threading.Tasks.dll中得到一个NullReferenceException,注释为“对象引用未设置为对象的实例。”。我试图使用Dispatcher而没有任何运气。这是我的代码的模拟(两个类都在同一名称空间中):

public partial class A : Window 
{
    private B _b;
    private Thread _bThread;
    private Dispatcher _bDispatcher;

    public A ()
    {
        InitializeComponent();

        _bThread = new Thread(() => 
        {
            try
            {
                _bDispatcher = Dispatcher.CurrentDispatcher;
                _b = new B();
                Dispatcher.Run();
            }
            catch (Exception ex)
            {
                Logger.Log(ex.message);
            }
        });
        _bThread.SetApartmentState(ApartmentState.STA);
        _bThread.Start();

       _b.VisibleChanged+= _b_VisibleChanged; // <= if this line is removed the program can start, but with this line I get the exception and the program crasches..
    }

    private void _b_VisibleChanged(object sender, EventArgs e)
    {
        // change margin values on A..
    }
}



public partial class B : Window
{

    private static EventHandlerList Events = new EventHandlerList();
    private static readonly object EventVisibleChanged = new object();

    public B () 
    {
        InitializeComponent();
        // other stuff
    }

    private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        TriggerOnVisibleChanged();
    }

    #region Triggers

    private void TriggerOnVisibleChanged()
    {
        ((EventHandler<EventArgs>)Events[EventVisibleChanged])?.Invoke(this, null);
    }

    #endregion

    #region Event add/remove handlers

    public event EventHandler<EventArgs> VisibleChanged
    {
        add
        {
            Events.AddHandler(EventVisibleChanged, value);
        }
        remove
        {
            Events.RemoveHandler(EventVisibleChanged, value);
        }
    }

    #endregion
}

我不知道我做错了什么,我不知道如何做这项工作,有人可以帮助我吗?

PS。这是为了wpf,而不是Forms .. DS。

PS2。我知道我不必创建自己的事件和触发器,可能只是在窗口B中使用了IsVisibleChanged事件,但我尝试了相同的结果...... DS。

1 个答案:

答案 0 :(得分:0)

我不相信你想要的东西是可能的,因为WPF使用的是一套公寓&#39;坚持线程亲和力的模型,即线程不能相互交互。

此外,您可能会更严格地陷入此陷阱......正如文章中所述&#34;具有线程亲和力的WPF对象派生自Dispatcher对象。&#34;

See here for more information on threading in WPF

编辑:为什么在多线程中呢?也许您正在寻找的是RoutedEventHandler(在子窗口中定义)...请参阅this SO post for an example