您的应用有一个主 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 与 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));
});