也許我錯誤地記住了Winforms的工作方式,或者我正在過度複雜化,但這是我的問題。WPF背景線程調用
我有一個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已經調用ShowDia日誌,因爲調用ShowDialog的暢通線程1(我相信的,因爲方式的WPF消息泵作品)
...最終效果是,我有彈出用戶同時多個登錄表單。
我想要的是讓用戶重新登錄到應用程序的同步方式......我在這裏錯過了什麼?
在此先感謝。
給Paul的答案增加一點細節,我相信他說你應該鎖定securityContext。這樣,一旦一個線程訪問並修改了securityContext(大概是登錄),那麼其他跟隨的線程將不會彈出登錄對話框,因爲securityContext在訪問時已經被設置。 – Dave 2010-04-27 04:06:38
好點。我應該提到我嘗試過....請考慮以下事項:1.後臺線程進入並調用Application Dispatcher線程,同時鎖定securityContextLock對象。 2.用戶單擊以最大化應用程序,並且真正的UI線程進入並嘗試訪問securityContext ...但它被鎖定....所以整個UI線程凍結...甚至認爲步驟1中的人管理爲了顯示登錄表單,UI線程被凍結,並且用戶不能與登錄表單交互。所以我們陷入僵局。 – Jeff 2010-04-27 04:17:57
我還應該提到忽略而不是阻塞不是一個選項,因爲任何要求securityContext的線程都會立即需要它來創建WCF通道憑證。 – Jeff 2010-04-27 04:32:42