繁体   English   中英

任务异步/等待无法在WPF中工作,因为它在其他情况下也可以工作

[英]Task async/await not working from WPF as it works in other scenarios

我遇到了一个非常奇怪的行为。 经过大量的挖掘,我发现了一个场景,该场景表明(显然)直接从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应用程序运行时,为什么不等待工作(相同方式)?

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM