Вызов фоновой темы WPF - PullRequest
       8

Вызов фоновой темы WPF

3 голосов
/ 27 апреля 2010

Возможно, я неправильно помню, как работает Winforms, или я слишком усложняю это, но вот моя проблема.

У меня есть клиентское приложение WPF, которое общается с сервером через WCF. Текущий пользователь может «выйти» из клиента WPF, который закрывает все открытые экраны, оставляет только панель навигации и минимизирует окно программы. Когда пользователь повторно максимизирует окно программы, ему предлагается войти в систему. Простой.

Но иногда вещи происходят в фоновых потоках - например, каждые 5 минут клиент пытается сделать вызовы WCF, которые обновляют некоторые кэшированные данные. А что если пользователь выйдет из системы при срабатывании этого 5-минутного таймера? Что ж, тогда пользователю нужно будет снова войти в систему ... и это, конечно, должно произойти в потоке пользовательского интерфейса.

    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();
       }
    }

Пока все хорошо, верно? Но что происходит, когда несколько потоков попадают в эту область кода?

Что ж, моя первая интуиция заключалась в том, что, поскольку я синхронизирую приложение.Current.Dispatcher, у меня все будет в порядке, и какой бы поток ни нажал первым, он будет отвечать за отображение формы входа и вход пользователя в систему ...

Не тот случай ...

  1. Поток 1 нажмет код и вызовет ShowDialog в форме входа

  2. Поток 2 также нажмет код и вызовет Login, как только поток 1 вызовет ShowDialog, поскольку вызов ShowDialog разблокирован, поток 1 (я полагаю, из-за того, как работает насос сообщений WPF)

... конечным результатом является то, что у меня одновременно появляется несколько форм входа в систему.

Все, что мне нужно, - это синхронизированный способ входа пользователя в приложение ... что мне здесь не хватает?

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 07 мая 2010

Извините за задержку с последующим наблюдением.

Я исправил проблему блокировки несколько дней назад в потоке пользовательского интерфейса, в основном реализовав DoEvents для WPF: http://khason.net/blog/how-to-doevents-in-wpf/

Так что теперь многие потоки, как фоновые, так и пользовательские, могут вызываться в потоке пользовательского интерфейса и, если окно уже показано, будут "эмулировать" поведение 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);
        }
1 голос
/ 27 апреля 2010

Возможно, немного блокировки?

Вы можете отслеживать записи и, возможно, игнорировать (не блокировать) другие действия опроса. Используйте одну точку входа, чтобы отобразить форму входа только один раз и подождите ...

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

Кроме того, рассмотрите возможность кэширования учетных данных пользователей, а не их повторного запроса, например SecureString:

http://msdn.microsoft.com/en-us/library/system.security.securestring.aspx

ПК: -)

...