簡體   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