簡體   English   中英

異步任務使程序掛起

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM