簡體   English   中英

WPF后台線程調用

[英]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. 線程1將命中代碼並在登錄表單上調用ShowDialog

  2. 線程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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM