简体   繁体   English

异步任务使程序挂起

[英]Asynchronous task makes program hang

I have a task that needs to call an http request to server and I do it like this:我有一个任务需要向服务器调用 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();

But it makes my UI hang.但这使我的 UI 挂起。

What is wrong with my code?我的代码有什么问题? Many thank for your comment.非常感谢您的评论。

You must await the Transform method, because the task returned is probably not completed yet instead of GetAwaiter().GetResult() .您必须等待Transform方法,因为返回的任务可能尚未完成,而不是GetAwaiter().GetResult() You'll probably never need to use these methods.您可能永远不需要使用这些方法。 GetResult() will block the current thread while the task is not completed. GetResult()将在任务未完成时阻塞当前线程。

This is a rough sketch, I have too little information about your structure:这是一个粗略的草图,我对您的结构的信息太少:

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);
}

If the caller isn't supporting async, you could try something like: (haven't tested it so, you'll have to check it)如果调用者不支持异步,你可以尝试类似:(还没有测试过,你必须检查一下)

The TaskScheduler.FromCurrentSynchronizationContext() is only needed when you are dealing with (for example) a UI thread.只有在处理(例如)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();

This line is blocking your UI thread, because of call to GetResult .由于对GetResult的调用,此行阻塞了您的 UI 线程。 Earlier you used async / await correctly, but in this line you are mixing async code with blocking code.之前您正确使用了async / await ,但在这一行中,您将异步代码与阻塞代码混合在一起。 You should use same approach as in Transform method and await the result instead of blocking using GetResult您应该使用与Transform方法相同的方法并await结果,而不是使用GetResult阻塞

To fix this simply change that line to要解决此问题,只需将该行更改为

priorityBb = await bb.Transform("epsg:3857");

Using GetResult like that can lead to deadlocks and in most situations is not a good idea.像这样使用GetResult会导致死锁,并且在大多数情况下并不是一个好主意。 Whenever you can just stick to async / await .只要你可以坚持async / await

If you can't make your caller async then your call can't be async .如果你不能让你的来电者async ,那么你的电话就不能是async的。 async / await is probably best approach here but if for some reason you can't use it you can wait for response and handle it on another thread using Task.Run async / await可能是这里最好的方法,但如果由于某种原因你不能使用它,你可以等待响应并使用Task.Run在另一个线程上处理它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM