7

Recently I found a method that performs all pending messages in the dispatcher queue until a specified priority. I already had such code before, but they use completely different methods. Here's both of them:

The PushFrame way:

/// <summary>
/// Enters the message loop to process all pending messages down to the specified
/// priority. This method returns after all messages have been processed.
/// </summary>
/// <param name="priority">Minimum priority of the messages to process.</param>
public static void DoEvents(
    DispatcherPriority priority = DispatcherPriority.Background)
{
    DispatcherFrame frame = new DispatcherFrame();
    Dispatcher.CurrentDispatcher.BeginInvoke(
        priority,
        new DispatcherOperationCallback(ExitFrame), frame);
    Dispatcher.PushFrame(frame);
}

private static object ExitFrame(object f)
{
    ((DispatcherFrame) f).Continue = false;
    return null;
}

Source: MSDN Library

The blocking Invoke way:

private static Action EmptyDelegate = delegate { };

/// <summary>
/// Processes all pending messages down to the specified priority.
/// This method returns after all messages have been processed.
/// </summary>
/// <param name="priority">Minimum priority of the messages to process.</param>
public static void DoEvents2(
    DispatcherPriority priority = DispatcherPriority.Background)
{
    Dispatcher.CurrentDispatcher.Invoke(EmptyDelegate, priority);
}

Source: Blog

Which is better and are there any functional differences between the two solutions?

Update: Here's number two with the delegate inlined, as in number one, making it even shorter:

/// <summary>
/// Processes all pending messages down to the specified priority.
/// This method returns after all messages have been processed.
/// </summary>
/// <param name="priority">Minimum priority of the messages to process.</param>
public static void DoEvents2(
    DispatcherPriority priority = DispatcherPriority.Background)
{
    Dispatcher.CurrentDispatcher.Invoke(new Action(delegate { }), priority);
}
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
ygoe
  • 18,655
  • 23
  • 113
  • 210

1 Answers1

5

You sort of answered your own question. It doesn't matter much which you pick since both do the same in the background.

Both run into this:

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

However PushFrame is a bit nicer since you do not need to create empty delegate.

dev hedgehog
  • 8,698
  • 3
  • 28
  • 55
  • Well, I need to create a delegate either way, and the PushFrame code is longer altogether. I just pulled out the static delegate instance (which my source already did) because I believe it might be a little faster to keep the memory allocated. But it's probably insignificant and I could as well inline that part, resulting in a single method. But it's good to know that both are actually the same. – ygoe Aug 22 '14 at 10:58
  • When using PushFrame, there is a problem with the main window re-size and move. https://connect.microsoft.com/VisualStudio/feedback/details/807292/wpf-application-intermittently-hangs-when-using-dispatcher-invoke-and-or-dispatcher-pushframe-while-user-is-resizing-or-draging-window – CaptainBli Dec 05 '14 at 20:24