检查异步任务状态并获取其结果

Posted

技术标签:

【中文标题】检查异步任务状态并获取其结果【英文标题】:Check status of async tasks status and get their results 【发布时间】:2021-09-09 15:32:37 【问题描述】:

我是 C# 新手。 我想在不等待响应的情况下启动 4 PostAsync,然后检查它们中的任何一个是否已完成并且 HTTP 响应包含特定单词,然后取消其他异步任务。

如果已完成的PostAsync 不包含单词或失败,则运行另一个任务,使所有异步任务的总数保持在 4

private async void Button_Click(object sender, RoutedEventArgs e)

    List<Task> tasks = new List<Task>();
    for (int ctr = 0; ctr <= 2; ctr++)
    
        tasks.Add(Web("https://google.com/api/", da));
    
    
    var index = Task.WhenAny(tasks).Result;


public static async Task<string> Web(string url, string da)

     var response = await client.PostAsync(url,
         new StringContent(da, Encoding.UTF8, "application/json"));

     return response.Content.ReadAsStringAsync().Result; ;

我测试了上面的代码,但不知道如何获取已完成任务的结果,也不知道如何在失败的情况下添加另一个任务。

【问题讨论】:

WhenAny() 方法返回完成的任务对象。而不是使用Result,这是错误的,因为它阻塞,否定使用WhenAny()的全部好处,写var task = await Task.WhenAny(tasks)task变量将包含完成的Task对象。至于取消其余的任务,只需确保任务是可取消的(即您已将取消令牌传递给每个任务),并触发取消令牌,即通过取消您在第一个获得令牌的取消令牌源地方。查看副本。 我会注意到变量名index 具有误导性,因为Task.WhenAny() 返回的值不是索引,而是任务。您似乎将WhenAny()WaitAny() 混淆了。 请查看以下问题:Async HTTP requests inside for loop without await 和 Task.WhenAny with cancellation of the non completed tasks and timeout。第一个可能正是您想要的。 截图:[PostAsync debug] 另一个问题的回答:***.com/a/69781897/11750551 【参考方案1】:

WhenAny 将返回第一个完成的任务。不是整数。为了得到结果,你可以等待同样的结果。

   var completedTask = Task.WhenAny(tasks);

   var result =await completedTask;

永远不要使用 task.result,因为它会阻止执行。

WhenAny 提供了一个异步迭代任务列表的选项。您可以直接在迭代循环中添加/删除要列出的任务。 (对于取消需要为所有任务传递相同的取消令牌)

【讨论】:

关于whenany的更多信息-请查看docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…

以上是关于检查异步任务状态并获取其结果的主要内容,如果未能解决你的问题,请参考以下文章

JDK 源码解析:深入浅出异步任务 FutureTask

使用celery的backend异步获取结果

C#异步编程概念和使用

解密函数计算异步任务能力之「任务的状态及生命周期管理」

Future和Callable 解析

Event事件