首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步任务使程序挂起

异步任务使程序挂起
EN

Stack Overflow用户
提问于 2020-04-21 12:49:11
回答 2查看 72关注 0票数 0

我有一个任务需要调用到服务器的http请求,我这样做:

代码语言:javascript
复制
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);
    ...
}
代码语言:javascript
复制
priorityBb = bb.Transform("epsg:3857").GetAwaiter().GetResult();

但它会让我的UI挂起。

我的密码怎么了?非常感谢您的评论。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-21 13:05:20

您必须等待Transform方法,因为返回的任务可能还没有完成,而不是GetAwaiter().GetResult()。您可能永远不需要使用这些方法。当任务未完成时,GetResult()将阻塞当前线程。

这是一个粗略的草图,我对你的结构了解得太少了:

代码语言:javascript
复制
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()

代码语言:javascript
复制
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());
}
票数 3
EN

Stack Overflow用户

发布于 2020-04-21 13:01:07

代码语言:javascript
复制
priorityBb = bb.Transform("epsg:3857").GetAwaiter().GetResult();

由于调用GetResult,这一行阻塞了您的UI线程。早些时候,您正确地使用了async/await,但在这一行中,您将异步代码与阻塞代码混合在一起。您应该使用与Transform方法和await方法相同的方法,而不是使用GetResult阻塞结果。

要解决这个问题,只需将该行更改为

代码语言:javascript
复制
priorityBb = await bb.Transform("epsg:3857");

像这样使用GetResult可能会导致死锁,而且在大多数情况下不是一个好主意。只要你能坚持使用async/await

如果你不能让你的呼叫者async,那么你的电话就不能是asyncasync/await可能是这里最好的方法,但是如果由于某种原因不能使用它,您可以等待响应并在另一个线程上使用Task.Run处理它

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61343956

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档