Click here to Skip to main content
Click here to Skip to main content

Application.DoEvents in WPF

, 20 Oct 2011
Rate this:
Please Sign up or sign in to vote.
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:

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:

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

Share

About the Author

Derek Lakin
Software Developer (Senior)
United Kingdom United Kingdom
No Biography provided

Comments and Discussions

 
QuestionUsing's PinmemberPallini23-Apr-14 1:35 
SuggestionFound another implementation on msdn PinmemberFilip D'haene28-Oct-11 11:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 20 Oct 2011
Article Copyright 2011 by Derek Lakin
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid