[英]Asynchronous task makes program hang
我有一個任務需要向服務器調用 http 請求,我這樣做:
public static async Task<BoundingBox> Transform(this BoundingBox boundingBox, string epsg) {
...
var min = _httpClient.GetStringAsync("https://epsg.io/trans?x=435951&y=5549182&s_srs=25832&t_srs=3857");
var max = _httpClient.GetStringAsync("https://epsg.io/trans?x=435911&y=5549122&s_srs=25832&t_srs=3857");
await Task.WhenAll(min, max);
...
}
priorityBb = bb.Transform("epsg:3857").GetAwaiter().GetResult();
但這使我的 UI 掛起。
我的代碼有什么問題? 非常感謝您的評論。
您必須等待Transform
方法,因為返回的任務可能尚未完成,而不是GetAwaiter().GetResult()
。 您可能永遠不需要使用這些方法。 GetResult()
將在任務未完成時阻塞當前線程。
這是一個粗略的草圖,我對您的結構的信息太少:
public class MyResults
{
public string Min {get;set;}
public string Max {get;set;}
}
public static async Task<MyResults> Transform(this BoundingBox boundingBox, string epsg) {
...
var minTask = _httpClient.GetStringAsync("https://epsg.io/trans?x=435951&y=5549182&s_srs=25832&t_srs=3857");
var maxTask = _httpClient.GetStringAsync("https://epsg.io/trans?x=435911&y=5549122&s_srs=25832&t_srs=3857");
await Task.WhenAll(minTask, maxTask);
// you can access the Results now, because all tasks are completed.
return new MyResults { Min = minTask.Result, Max = minTask.Result };
}
public static async Task GetMyData()
{
var myResults = await bb.Transform(".....");
// ^^^^^
Console.WriteLine(myResults.Min);
Console.WriteLine(myResults.Max);
}
如果調用者不支持異步,你可以嘗試類似:(還沒有測試過,你必須檢查一下)
只有在處理(例如)UI 線程時才需要TaskScheduler.FromCurrentSynchronizationContext()
。
public static void GetMyData()
{
// You are not able to await it here. Fire and "forget"
Task.Run<MyResults>(() =>
{
// Not executed on the UI thread
return bb.Transform(".....");
})
.ContinueWith(transformTask =>
{
// back on the UI thread.....
var myResults = transformTask.Result;
Console.WriteLine(myResults.Min);
Console.WriteLine(myResults.Max);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
priorityBb = bb.Transform("epsg:3857").GetAwaiter().GetResult();
由於對GetResult
的調用,此行阻塞了您的 UI 線程。 之前您正確使用了async
/ await
,但在這一行中,您將異步代碼與阻塞代碼混合在一起。 您應該使用與Transform
方法相同的方法並await
結果,而不是使用GetResult
阻塞
要解決此問題,只需將該行更改為
priorityBb = await bb.Transform("epsg:3857");
像這樣使用GetResult
會導致死鎖,並且在大多數情況下並不是一個好主意。 只要你可以堅持async
/ await
。
如果你不能讓你的來電者async
,那么你的電話就不能是async
的。 async
/ await
可能是這里最好的方法,但如果由於某種原因你不能使用它,你可以等待響應並使用Task.Run
在另一個線程上處理它
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.