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

Application.DoEvents in WPF

0.00/5 (No votes)
20 Oct 2011 1  
Implementing Application.DoEvents in WPF.

Recently I’ve been trying to make some thumbnail generation code synchronous. I’m trying to grab the first frame from a Shockwave Flash (SWF) or Flash Video (FLV) file and save it as a thumbnail, but in order to do that, I needed to create a window to host an ActiveX control that renders the Flash file so that I can then use RenderTargetBitmap to grab a frame.

The code sits inside a handler for the ContentRendered event of the window and is initialised like this:

C#
1:  public bool CreateThumbnail(string sourcePath, string targetPath)
   2:  {
   3:      // NOTE: Loads of code missed for brevity.
   4:      ManualResetEvent waitHandle = new ManualResetEvent(false);
   5:      bool generated = false;
   6:   
   7:      var win = new Window()
   8:      {
   9:          AllowsTransparency = true,
  10:          Opacity = 0.0,
  11:          Left = 0,
  12:          Top = 0,
  13:          SizeToContent = SizeToContent.WidthAndHeight,
  14:          ShowInTaskbar = false,
  15:          WindowStyle = WindowStyle.None
  16:      };
  17:      win.ContentRendered += (sender, e) =>
  18:      {
  19:          // Use RenderTargetBitmap to get the frame and save it.
  20:          generated = true;
  21:          waitHandle.Set();
  22:      }
  23:   
  24:      win.Show();
  25:      waitHandle.WaitOne(5000);
  26:      return generated;
  27:  }

The problem is that the ContentRendered event doesn’t fire until after the WaitOne call on the ManualResetEvent, effectively meaning that thumbnail generation fails all the time. Basically, the UI thread is blocked waiting for the wait handle to be signaled, so it doesn’t get round to rendering the window until after this method has called.

For VB programmers out there, you may be thinking that you simply call Application.DoEvents() to free up the message loop and unfortunately WPF doesn’t provide the same API. However, there is a way to do this in WPF. By pushing a nested message loop, we can cause this nested message loop to be processed immediately, allowing the window’s content to be rendered and our thumbnail to be generated. I wouldn’t recommend using nested message loops and neither would many other people, but in this case, it works for me. All I needed to do was to add the following line of code between the win.Show() call and the waitHandle.WaitOne(5000) call above:

C#
Application.Current.Dispatcher.Invoke(
    DispatcherPriority.Background, 
    new ThreadStart(delegate { }));

Thanks to Zhou Young’s post for the simplest implementation of DoEvents in WPF that I’ve seen. As you can see, he’s put it in his Application class, but personally I think that’s just encouraging you to use this approach and in most cases, I think there’s a better solution for you.

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