Hello Guest

I may not remember correctly how Winforms works, or I'm too exhausting, but here is my problem.

I have a WPF client application that talks to a server through WCF. The current user can "exit" the WPF client, which closes all open screens, leaves only the navigation bar and minimizes the program window. When the user re-maximizes the program window, they will be prompted to log in. Plain.

But sometimes this happens in the background threads - like every 5 minutes the client tries to make WCF calls that update some cached data. And what if a user logs out when this 5 minute timer fires? Well, then the user should be prompted to log in ... and this, of course, should happen in the user interface thread.

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

So far so good, right? But what happens when multiple threads get to this place in the code?

Well, my first intuition was that since I am synchronizing through Application.Current.Dispatcher, I have to be fine, and no matter who is the first, I will be responsible for displaying the login form and enabling the user in the system .. .

Not that case ...

  • A code will appear in thread 1 and call ShowDialog in the login form

  • Thread 2 Login, Thread 1 ShowDialog, ShowDialog Thread 1 ( , - , WPF)

... , .

, , ... ?

.

+3
2

.

, 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

Source: https://habr.com/ru/post/1742922/


All Articles