Understanding the true behavior of the DispatcherPriority enum provided in WPF

10,434

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.

Share:
10,434
William
Author by

William

Updated on June 15, 2022

Comments

  • William
    William almost 2 years

    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?

  • Ole K
    Ole K over 3 years
    If you prefer to do it quick, use the highest priority of Send
  • Peter Drier
    Peter Drier almost 3 years
    You can actually see if the dispatcher is busy by having a background thread update a property via InvokeAsync on a low priority. I use that with DateTime.Now to see if the app is "frozen" to the end user. Beyond that, it can come in handy when optimizing background updates from an INotifyPropertyChanged object through the DependencyObject PropertyChange bits. Most people shouldn't be doing that though, it's not straightforward to get right.