您应该将数据密集型工作放在后台线程上,以便 UI 可以正确更新。这提供了最佳的用户体验。
用一些代码详细说明 FZysset 的答案...
private async void Next_Click(object sender, RoutedEventArgs e)
{
footerText.Text = "Waiting for dataRetreival";
IsEnabled = false;
await SomeRandomTimeTakingMethodAsync();
IsEnabled = true;
footerText.Text = "Ready";
}
private async Task SomeRandomTimeTakingMethodAsync()
{
await Task.Delay(TimeSpan.FromSeconds(new Random().Next(2, 5)));
// or await Task.Run(() => { ... });
}
上面的示例允许您利用 .NET 4.5 中引入的 await/async。注意它流动得有多好?废话不多说!
我们将内容放到后台线程中,以便 UI 可以保持畅通(因此它会在状态栏上显示您的更新并允许用户交互。)当然,您必须小心不要更新 UI 上的任何内容来自您的后台线程。
如果您使用的是旧版本的 .NET,则可以只使用 TPL 而不使用 async/await:
private void Next_Click(object sender, RoutedEventArgs e)
{
footerText.Text = "Waiting for dataRetreival";
IsEnabled = false;
Task.Factory.StartNew(() =>
{
SomeRandomTimeTakingMethod();
}).ContinueWith(t =>
{
IsEnabled = true;
footerText.Text = "Ready";
}, TaskScheduler.FromCurrentSynchronizationContext());
}
private void SomeRandomTimeTakingMethod()
{
Thread.Sleep(TimeSpan.FromSeconds(new Random().Next(2, 5)));
}
关于后一个示例需要注意两点:
- 您必须将
TaskScheduler.FromCurrentSynchronizationContext() 提供给ContinueWith 调用,否则您将遇到异常,因为延续不在UI 线程上。您必须在不在后台线程上运行的方法中获取上下文。
- 您需要检查
ContinueWith 中Task 对象的异常情况。
虽然这个例子非常简陋。如果您要使用点击处理程序启动一堆后台操作,您会希望给自己一些帮助类/服务以使生活更轻松。 (并调查 MVVM,我不知道你是否正在使用它。)
我的一位同事做了一个关于在 C# 和 .NET 中使用各种异步模式的演示。你可以在这里查看:https://github.com/mtusk/TplLunchAndLearn