在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... )
中的语句吗?谢谢你的帮助。
你的应用程序有一个主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.BeginInvoke
和object.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");
});
}