任务异步/等待在 WPF 中不起作用,因为它在其他方案中有效

本文关键字:因为 其他 方案 有效 不起作用 等待 异步 WPF 任务 | 更新日期: 2023-09-27 18:34:55

我遇到了一个非常奇怪的行为。经过大量挖掘,我能够找到一个场景,该场景表明(显然(直接从 WFP 应用程序使用任务等待无法按预期工作。但是,创建任务并在其中执行等待可以正常工作。

我使用以下步骤进行说明(使用VS 2013(。在新的 WPF 应用程序中,请使用以下 main.xaml.cs:

using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        static async Task<bool> Test_int()
        {
            TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
            Thread t = new Thread(() =>
            {
                Thread.Sleep(1000);
                tcs.SetResult(true);
                //Console.WriteLine("TCS set");
            });
            t.Start();
            //int i = tcs.Task.Result;   //<-- this always works, but doesn't take    advantage of await semantics
            var ret = await tcs.Task;
            return ret;
        }
        static void Test()
        {
            var tt = Test_int();
            //(1)
            tt.Wait();
            //Console.WriteLine("Test done");
        }
        public MainWindow()
        {
            InitializeComponent();
            //option 1 -- works
            Task t = new Task(Test);
            t.Start();
            t.Wait();
            //option 2 -- hangs indefinitely
            Test();
        }
    }
}

我看到的行为是运行方法Test((直接导致应用程序挂起(在标有(1(的等待行中(,而在任务中运行它正确运行并完成。

我通过在任务上下文中运行解决了原始问题,但我想了解问题的原因。顺便说一句,在控制台应用程序中运行时,相同的 Test(( 方法确实直接工作。

为什么直接从 WPF 应用程序运行时等待不起作用(以相同的方式(?

任务异步/等待在 WPF 中不起作用,因为它在其他方案中有效

您遇到了我在博客上描述的经典死锁场景。总之,默认情况下,await将捕获"上下文"并使用它来恢复async方法。在本例中,它是一个 UI 上下文,如果阻止 UI 线程(通过调用 Wait (,则 async 方法无法恢复且永远不会完成。

正确的解决方案是使用 await 而不是 Wait .

此外,不应使用 Task 构造函数、StartThread(请改用 Task.Run,但仅当需要在后台线程上执行代码时(。

我建议您阅读我的async介绍博客文章,然后阅读我的async最佳实践 MSDN 文章。他们应该帮助你。

相关文章: