繁体   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