在WPF应用程序中使用c#分派器

本文关键字:分派 WPF 应用程序 | 更新日期: 2023-09-27 18:11:45

我正在构建一个聊天客户端,我不是100%确定如何使用dispatcher。问题是我有这样一个方法:

public void LostConnection()
{
    myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "'r'n");
}

我需要用Dispatcher.Invoke包围(myGUI.chatBox... )中的语句吗?谢谢你的帮助。

在WPF应用程序中使用c#分派器

你的应用程序有一个主UI线程(通常是ManagedThreadId==1)。通常在聊天应用程序中,您的事件将通过其他线程(专用套接字侦听线程或来自侦听代码的线程池线程)进入。如果你想从一个事件中更新UI,而这个事件被其他线程拉出,你必须使用分派器。这里一个有用的测试是Dispatcher.CheckAccess()方法,如果代码在UI线程上返回true,如果在其他线程上返回false。一个典型的调用看起来像这样:

using System.Windows.Threading; // For Dispatcher.
if (Application.Current.Dispatcher.CheckAccess()) {
    network_links.Add(new NetworkLinkVM(link, start_node, end_node));
}
else {
    Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(()=>{
        network_links.Add(new NetworkLinkVM(link, start_node, end_node));
    }));
}

如果你在主窗口,你可以使用:

Dispatcher.BeginInvoke(...

如果你在其他环境中,例如视图模型,那么使用:

Application.Current.Dispatcher.BeginInvoke(  

Invoke与BeginInvoke
如果你想让当前线程等待UI线程处理完调度代码,使用Invoke;如果你想让当前线程不等待UI线程的操作完成,使用BeginInvoke

MessageBox, Dispatchers和Invoke/BeginInvoke:
Dispatcher.Invoke将阻塞你的线程,直到MessageBox被解除。
Dispatcher.BeginInvoke将允许你的线程代码继续执行,而UI线程将阻塞在MessageBox调用上,直到它被解除。

CurrentDispatcher vs . Current.Dispatcher!
注意Dispatcher.CurrentDispatcher,因为我对它的理解是,它将为当前线程返回Dispatcher,而不是UI线程。通常你对UI线程上的调度程序感兴趣——Application.Current.Dispatcher总是返回这个。

额外注意:
如果你发现你必须经常检查调度程序CheckAccess,那么一个有用的辅助方法是:

public void DispatchIfNecessary(Action action) {
    if (!Dispatcher.CheckAccess())
        Dispatcher.Invoke(action);
    else
        action.Invoke();
}

可称为:

DispatchIfNecessary(() => {
    network_links.Add(new NetworkLinkVM(link, start_node, end_node));
});

我对Application.Current.Dispatcher.BeginInvokeobject.Invoke()方法有问题。

这个为我工作:

Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
{
     // code...
}));

像这样的东西(off the top of my head)应该可以工作:

public void LostConnection() 
{ 
   myGUI.Invoke
      ((MethodInvoker)delegate
   {
      myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "'r'n"); 
   });
}