也许我记错了 Winforms 的工作原理,或者我把这件事搞得太复杂了,但这是我的问题。
我有一个 WPF 客户端应用程序,它通过 WCF 与服务器通信。当前用户可能会“注销” WPF 客户端,这会关闭所有打开的屏幕,只留下导航窗格,并最小化程序窗口。当用户重新最大化程序窗口时,会提示他们登录。简单。
但有时事情会发生在后台线程上——比如客户端每 5 分钟尝试进行一次 WCF 调用以刷新一些缓存的数据。如果在这个 5 分钟计时器触发时用户退出了怎么办?那么,应该提示用户重新登录......这当然必须发生在 UI 线程上。
private static ISecurityContext securityContext;
public static ISecurityContext SecurityContext
{
get
{
if (securityContext == null)
{
// Login method shows a window and prompts the user to log in
Application.Current.Dispatcher.Invoke((Action)Login);
}
return securityContext;
}
}
private static void Login()
{
if (securityContext == null) { \
/* show login window and set securityContext */
var w = new LoginWindow();
w.ShowDialog();
securityContext = w.GetSecurityContext();
}
}
到目前为止一切顺利,对吧?但是当多个线程碰到这个代码点时会发生什么?
好吧,我的第一个直觉是,由于我正在跨 Application.Current.Dispatcher 同步,所以我应该没问题,无论哪个线程首先命中都将负责显示登录表单并让用户登录......
不是这样的...
线程 1 将点击代码并在登录表单上调用 ShowDialog
线程 2 也将命中代码,并在线程 1 调用 ShowDialog 后立即调用 Login,因为调用 ShowDialog 未阻塞线程 1(我相信是因为 WPF 消息泵的工作方式)
...最终效果是我一次向用户弹出了多个登录表单。
我想要的只是让用户重新登录到应用程序的同步方式......我在这里错过了什么?
提前致谢。