了解 WPF 中提供的 DispatcherPriority 枚举的真实行为
Understanding the true behavior of the DispatcherPriority enum provided in WPF
what each enum does 上有包含定义的文档。但是我如何才能 demo/see 在实践中做到这一点?我怎么可能知道什么时候使用哪个优先级?
这是我创建的一些代码,试图查看优先级如何影响排序,它为我提供了排序正确的证据(第一个循环迭代将向调度队列添加一个 SystemIdle 枚举),但它仍然被添加到字符串 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());
}
并且输出顺序保持不变,即使列表被颠倒(在分配 vals
之后添加此行):
vals.Reverse();
那么,在确定我应该分配哪个调度优先级时,还有什么我可以使用的吗?
在 Prism Framework 中,包装 Dispatcher
的 DefaultDispatcher
使用 Normal
优先级。这应该是几乎所有应用场景的基础。
/// <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);
}
}
}
只要您不在 UI 线程上 运行 设置任何实际逻辑,我建议您这样做。
如果您出于某种原因想要 运行 "quick" 线程上的逻辑,您可以遵循建议 here 并坚持 Background
.
我确实稍微研究了一下,我在 NuGet's source 中发现了一些用法,他们使用 Send
、Normal
、Background
和 ApplicationIdle
来表示各种原因,但在我的 WPF 开发中,我从来没有将 DispatcherPriority
的使用微调到这种程度。
what each enum does 上有包含定义的文档。但是我如何才能 demo/see 在实践中做到这一点?我怎么可能知道什么时候使用哪个优先级?
这是我创建的一些代码,试图查看优先级如何影响排序,它为我提供了排序正确的证据(第一个循环迭代将向调度队列添加一个 SystemIdle 枚举),但它仍然被添加到字符串 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());
}
并且输出顺序保持不变,即使列表被颠倒(在分配 vals
之后添加此行):
vals.Reverse();
那么,在确定我应该分配哪个调度优先级时,还有什么我可以使用的吗?
在 Prism Framework 中,包装 Dispatcher
的 DefaultDispatcher
使用 Normal
优先级。这应该是几乎所有应用场景的基础。
/// <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);
}
}
}
只要您不在 UI 线程上 运行 设置任何实际逻辑,我建议您这样做。
如果您出于某种原因想要 运行 "quick" 线程上的逻辑,您可以遵循建议 here 并坚持 Background
.
我确实稍微研究了一下,我在 NuGet's source 中发现了一些用法,他们使用 Send
、Normal
、Background
和 ApplicationIdle
来表示各种原因,但在我的 WPF 开发中,我从来没有将 DispatcherPriority
的使用微调到这种程度。