[英]WPF Background Thread Invocation
也許我錯誤地記得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消息泵的工作方式)
...最終結果是我有多個登錄表單一次彈出給用戶。
我想要的只是讓用戶重新登錄應用程序的同步方式......我在這里缺少什么?
提前致謝。
也許有點鎖定?
您可以監視條目,也可以忽略(不阻止)其他輪詢操作。 使用單個入口點只顯示一次登錄表單並等待...
http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx
另外,請考慮緩存用戶憑據而不是重新提示它們,例如SecureString:
http://msdn.microsoft.com/en-us/library/system.security.securestring.aspx
PK :-)
對不起延遲的跟進。
我幾天前在UI線程上通過基本實現WPF的DoEvents修復了阻塞問題: http : //khason.net/blog/how-to-doevents-in-wpf/
所以現在,許多線程,后台和UI都可以調用UI線程,如果窗口已經顯示,將“模擬”ShowDialog的行為,但不會阻止,也不會顯示第二個登錄窗口...希望這樣做任何閱讀的人都有意義
void ShowLoginWindow(Window window)
{
if (window != null )
{
if (window.Visibility != Visibility.Visible)
{
try
{
result = window.ShowDialog();
}
catch (Exception ex)
{
}
}
else
{
// don't block the UI thread, but wait till the dialog window returns
while(window.Visibilit y== Visibility.Visible)
{
DoEvents();
}
return window.DialogResult;
}
}
return result;
}
void DoEvents()
{
DispatcherFrame f = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
(SendOrPostCallback)delegate(object arg)
{
DispatcherFrame fr = arg as DispatcherFrame;
fr.Continue = false;
}, f);
Dispatcher.PushFrame(f);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.