我正在构建一个聊天客户端,并不是100%确定如何使用dispatcher
。所以问题是我有一个方法:
public void LostConnection()
{
myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n");
}
我是否需要使用(myGUI.chatBox... )
在Dispatcher.Invoke
内填写声明?我感谢任何帮助。
答案 0 :(得分:76)
您的应用有一个主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(
调用vs BeginInvoke
如果希望当前线程等到UI线程处理了调度代码,请使用Invoke
;如果希望当前线程继续而不等待UI线程上的操作完成,请使用BeginInvoke
。
MessageBox,Dispatchers和Invoke / BeginInvoke:
Dispatcher.Invoke
将阻止您的线程,直到MessageBox被解雇
Dispatcher.BeginInvoke
将允许您的线程代码继续执行,而UI线程将阻止MessageBox调用,直到它被解除。
CurrentDispatcher vs Current.Dispatcher!
是Dispatcher.CurrentDispatcher
的商品,因为我对此的理解是,它将返回当前线程而不是UI线程的Dispatcher。通常,您对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));
});
答案 1 :(得分:2)
这样的事情(在我的头顶)应该有效:
public void LostConnection()
{
myGUI.Invoke
((MethodInvoker)delegate
{
myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n");
});
}
答案 2 :(得分:0)
我在Application.Current.Dispatcher.BeginInvoke
和object.Invoke()
方法上遇到了问题。
这对我有用:
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
{
// code...
}));