Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding the true behavior of the DispatcherPriority enum provided in WPF

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?

like image 841
William Avatar asked Nov 13 '15 20:11

William


1 Answers

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.

like image 106
Ethan Cabiac Avatar answered Nov 05 '22 23:11

Ethan Cabiac