Understanding the true behavior of the DispatcherPriority enum provided in WPF

William picture William · Nov 13, 2015 · Viewed 8.7k times · Source

There is documentation with definitions on what each enum does. But how am I able to demo/see this in practice? And how can I possibly know when to use which priority?

Here's some code I have created in attempt to see how the priorty affects the ordering, and it provides me with proof that the ordering is correct (the first loop iteration will have added a SystemIdle enum to the dispatch queue), but it still got added to the string last

private void btn_Click(object sender, RoutedEventArgs e)
    {
        StringBuilder result = new StringBuilder();
        new Thread(() =>
            {

                var vals = Enum.GetValues(typeof(DispatcherPriority)).Cast<DispatcherPriority>().Where(y => y >= 0).ToList();
                vals.Reverse();
                vals.ForEach(x =>
                    { 
                        Dispatcher.BeginInvoke(new Action(() =>
                        {
                            result.AppendLine(string.Format("Priority: {0} Enum:{1}", ((int)x), x.ToString()));
                        }), x);
                    });


            }).Start();

        ShowResultAsync(result, 2000);
    }

    private async void ShowResultAsync(StringBuilder s, int delay)
    {
        await Task.Delay(delay);
        MessageBox.Show(s.ToString());
    }

enter image description here

and the output order stays the same, even when the list is reversed (added this line just after vals gets assigned):

vals.Reverse();

So once again, is there anything more I can use when determining which dispatch priority I should assign?

Answer

Ethan Cabiac picture Ethan Cabiac · Nov 13, 2015

In the Prism Framework the DefaultDispatcher which wraps Dispatcher uses a Normal priority. This should be the bread-and-butter for nearly all application scenarios.

/// <summary>
/// Wraps the Application Dispatcher.
/// </summary>
public class DefaultDispatcher : IDispatcherFacade
{
    /// <summary>
    /// Forwards the BeginInvoke to the current application's <see cref="Dispatcher"/>.
    /// </summary>
    /// <param name="method">Method to be invoked.</param>
    /// <param name="arg">Arguments to pass to the invoked method.</param>
    public void BeginInvoke(Delegate method, object arg)
    {
        if (Application.Current != null)
        {
            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, method, arg);
        }
    }
}

As long as you are not running any actual logic on the UI thread I would recommend doing this.

If you did for some reason want to run "quick" logic on the UI thread you could follow the advice here and stick with a value of Background.

I did look into it a little and I found some usages in NuGet's source where they use Send, Normal, Background and ApplicationIdle for various reasons but in my WPF development I have never had to fine tune usage of DispatcherPriority to this degree.