[英]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
構造函數, Start
或Thread
(而應使用Task.Run
,而僅當您需要在后台線程上執行代碼時)。
我建議您閱讀我的async
介紹博客文章 ,然后閱讀我的async
最佳實踐MSDN文章 。 他們應該幫助您。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.