Question

The situation

I'll try to explain my Problem with a small example. I have a class that manages a view-stack. Replaces views shows and initializes them etc.

class ViewManager()
{
    void ReplaceView()
    {
        RemoveView(...);
        InitializeView(...); // this code may call Application.DoEvents()
        AddNewView(...);
    }

    void ShowModalView()
    {
        ShowView();
        Dispatcher.PushFrame()
        ....
        // wait until view can be removed
        RemoveView();
    }

   void RemoveView()
   {
     ...
   }
   // ... more functions
}

Because the ViewManager does a lot with UI elements, other Threads uses the ViewManager through Dispatcher.Invoke.

Dispatcher.Invoke(new Action(() => m_viewManager.Remove(someView)));

If now multiple threads Invoke actions on the ViewManager, and one of them calls deep down somewhere in the code Application.DoEvents or DispatcherPushFrame, a second MessageLoop is spawned that will invoke another method o n the view Manager.

The Problem:

  • ShowModalView is called and calls PushFrame.
  • During ShowModalView another thread calls ShowModalView or ReplaceView.
  • Because the new message loop executes all tasks queued to the dispatcher this method are also executed.
  • Therefore two methods of the ViewManager are executed "at the same time" - or better because it is the same thread - nested in each other.

Locking inside the ViewManager is useless, because it is all the same thread. A semaphore might freeze the UI thread, because during the Message loop of the "ShowModalView" another thread can invoke ShowModalView on the dispatcher and that will freeze the UI thread.

The Questions:

  • During the "ShowModalView" the UI thread should handle input / paint etc but should not handle other tasks invoked through "Dispatcher.Invoke" Is this possible?
  • Do you have other Ideas to solve this problem?

Thank you for your hints and answers

Manuel

EDIT: One solution might be to get rid of all DoEvents and PushFrame code. This is very hard to achieve but probably the only right solution. This post explains a part of my Problem

Use of Application.DoEvents

Was it helpful?

Solution

As Servy said, get rid of Application.DoEvents() and Dispatcher.PushFrame is the only clean solution. Sometimes this will cause a lot of refactoring but it is worth the effort.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top