繁体   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