Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

DispatcherFrame. Look in-Depth

0.00/5 (No votes)
31 Jan 2011 1  
DispatcherFrame. Look in-Depth

Introduction

Have you ever wondered what exactly DispatcherFrame is? This article will explain it to you.

DispatcherFrame. Look in-Depth

I think that almost all of you heard about DispatcherFrame. Let’s try to understand what is it and where it can be used? MSDN said: “Represent an execution loop in the Dispatcher”. Not enough information to understand and use it as I think. Also, there is an example of a very useful procedure, but also, not obvious to understand. Here it is:

[SecurityPermissionAttribute(SecurityAction.Demand, 
	Flags = SecurityPermissionFlag.UnmanagedCode)]
public void DoEvents()
{   
  DispatcherFrame frame = new DispatcherFrame();   
  Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,    
     new DispatcherOperationCallback(ExitFrame),
  frame);   
  Dispatcher.PushFrame(frame);
}
 
public object ExitFrame(object f)
{
  ((DispatcherFrame)f).Continue = false;
  return null;
} 

This procedure is DoEvents. As you can guess from its title – it forces events to be performed. So, let’s understand DispatcherFrame and how this method works.

Let’s start with the Dispatcher class. I think everybody who works with WPF knows what it is. It is a class that works with UI thread in WPF. It contains a queue of items that should be performed. I hope that everybody knows about Dispatcher and I don’t need to describe it in detail.

To understand how Dispatcher works, I use ildasm.exe utility to disassemble WindowsBase assembly. I found Dispatcher class and look at its IL. There is a method Run() which starts the Dispatcher work. Let’s look inside this method:

IL_0000:newobj
instance void System.Windows.Threading.DispatcherFrame ::.ctor()
IL_0005:call
void System.Windows.Threading.Dispatcher::PushFrame
	(class System.Windows.Threading.DispatcherFrame)  

New DispatcherFrame is created and PushFrame() method is called. Let’s go to the implementation of this method (I include here only the important lines):

IL_0039:ldarg.0
IL_0043:call
  instance bool System.Windows.Threading.Dispatcher::GetMessage(valuetype
  System.Windows.Interop.MSG&, int, int32, int32)
 
IL_004d:
call instance void
  System.Windows.Threading.Dispatcher::TranslateAndDispatchMessage(valuetype
  System.Windows.Interop.MSG&)
 
IL_0053:
  callvirt instance bool System.Windows.Threading.DispatcherFrame::get_Continue()
IL_0058: 
  brtrue.s IL_0039 

In a friendly manner, it looks like:

While (dispatcherFrame.Continue)
{
  Dispatcher.GetMessage();
  Dispatcher.TranslateAndDispatch();
}

So, while dispatcherFrame’s Continue property is true, this cycle of reading system messages will be executed.

Let’s return to the MSDN definition: “Represent an execution loop in the Dispatcher”. Exactly this WHILE statement is represented by DispatcherFrame.

When the application is started, Dispatcher.Run() is called. Dispatcher creates a default DispatcherFrame which represents the main message loop in application. You can call Dispatcher.PushFrame(DispatcherFrame frame) to start a new loop described above. Main loop will be “paused” until new DispatcherFrame.Continue = false.

Now, let's return to DoEvents() for WPF.

[SecurityPermissionAttribute(SecurityAction.Demand,
Flags = SecurityPermissionFlag.UnmanagedCode)]
public void DoEvents()
{
  DispatcherFrame frame = new DispatcherFrame();
  Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, 
     new DispatcherOperationCallback(ExitFrame), frame);
  Dispatcher.PushFrame(frame);
}
 
public object ExitFrame(object f)
{
  ((DispatcherFrame)f).Continue = false;
  return null;
}  

Let’s skip the security attribute and go forward. Say, we have a very huge set of operations that should be performed in UI thread and while this application GUI should be updated. Since our operations are performed in UI thread, GUI will not be updated because Dispatcher will be busy by these operations.

How Can This Problem be Solved?

In DoEvents(), there is created new DispatcherFrame (frame variable) and one “Invoke” for dispatcher with Background priority, which sets that frame shouldn’t be continued (frame.Continue=false). Background priority is lowest.

When you call DoEvents(), there is a set of items in Dispatcher that should be performed. Also, this set contains an item which should update our GUI and should be performed ASAP. When PushFrame() is called, the main loop is suspended and a new loop starts (as described above). Dispatcher begins to get system messages AND to process items queue depending on its priority. Dispatcher will process all items and one of those items is operation that stops our new loop. It has the lowest priority and will be performed last. After the operation is invoked, new loop is stopped and the flow returns to the main loop and huge operations processing.

History

  • 31st January, 2011: Initial post

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here