带有延续场景的简单异步操作在WPF应用程序上不起作用
本文关键字:WPF 应用 应用程序 不起作用 程序上 异步操作 简单 延续 | 更新日期: 2023-09-27 18:17:11
为了尝试异步操作,我在WPF应用程序上进行了一个非常简单的操作。下面是我的完整代码:
static int GetPrimes() {
var query =
from n in Enumerable.Range(3, 5000000).AsParallel()
where Enumerable.Range(2, (int)Math.Sqrt(n)).All(i => n % i > 0)
select n;
return query.Count();
}
private void button1_Click(object sender, RoutedEventArgs e) {
Task<int> task = Task.Factory.StartNew(
() => GetPrimes(),
TaskCreationOptions.LongRunning
);
task.ContinueWith(x => {
label1.Content = task.Result;
});
}
正如你所看到的,当我按下按钮时,它做了一些事情,当它完成时,它需要将结果推送给标签,但它没有这样做。
我同步测试了这个,它工作了。
我在这里错过了什么?
你没有解释"it doesn't do that"是什么意思。我假设你得到一个异常,因为你试图操纵一个UI元素从错误的线程?
问题是这段代码:
task.ContinueWith(x => {
label1.Content = task.Result;
});
你没有指定你想在哪个线程上运行你的continuation,所以它可以在任何线程上运行。它可能会运行在与第一个任务相同的线程上,即线程池线程。由于不允许从创建UI的线程以外的线程访问UI,这意味着您的label1.Content
赋值将异常失败。
修复方法很简单:在UI线程上运行continuation。将上面的代码更改为:
task.ContinueWith(x => {
label1.Content = task.Result;
}, TaskScheduler.FromCurrentSynchronizationContext());
由于您正在处理后台线程,因此您需要将任何与UI有关的代码编组到UI线程中。
task.ContinueWith(x => {
Dispatcher.Invoke(() =>
{
label1.Content = task.Result;
},
null);
});