带有延续场景的简单异步操作在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; 
    });
}

正如你所看到的,当我按下按钮时,它做了一些事情,当它完成时,它需要将结果推送给标签,但它没有这样做。

我同步测试了这个,它工作了。

我在这里错过了什么?

带有延续场景的简单异步操作在WPF应用程序上不起作用

你没有解释"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);
});