处理不同结果类型的异步任务,随着它们完成。

huangapple go评论68阅读模式
英文:

Process async tasks of different result types as they complete

问题

我试图在异步任务完成时/当它们完成时处理每个任务的结果。这些任务具有不同的结果集。我希望并行执行这些任务,但需要在任何任务完成时处理结果。

有很多谷歌搜索结果关于异步函数具有相同的返回类型,但是,我找不到一个具有不同结果集的示例。

private async Task CompleteTasksAsync()
{
    var taskA = GetStringAsync();
    var taskB = GetIntAsync();
    var taskC = GetStringListAsync();
    var taskD = GetGenericAsync<double>(1d);

    await Task.WhenAll(taskA, taskB, taskC, taskD); // 此语句将等待
                                                    // 直到所有任务完成

    // 当任务A完成时,打印 taskA.Result
    // 当任务B完成时,打印 taskB.Result
    // 当任务C完成时,打印 taskC.Result
    // 当任务D完成时,打印 taskD.Result
}

private Task<string> GetStringAsync() => Task.FromResult("string");
private Task<int> GetIntAsync() => Task.FromResult(1);
private Task<List<string>> GetStringListAsync()
    => Task.FromResult(new List<string> { "string" });
private Task<T> GetGenericAsync<T>(T data) => Task.FromResult(data);
英文:

I am trying to process each async task result when/as they complete. These tasks have different result sets. I like to execute these tasks concurrently but need to process the result when any finishes.

There are many google search results when async functions have the same return type, however, I couldn't get my hand to one with different result sets.

private async Task CompleteTasksAsync()
{
    var taskA = GetStringAsync();
    var taskB = GetIntAsync();
    var taskC = GetStringListAsync();
    var taskD = GetGenericAsync&lt;double&gt;(1d);

    //var tasks = new[] {taskA, taskB, taskC, taskD} // this will only work if all
                                                     // tasks have same return type

    await Task.WhenAll(taskA, taskB, taskC, taskD); // This statement will wait
                                                    // until all tasks are completed

    // when Task A finished Console.WriteLine(taskA.Result);
    // when Task B finished Console.WriteLine(taskB.Result);
    // when Task C finished Console.WriteLine(taskC.Result);
    // when Task D finished Console.WriteLine(taskD.Result);
}

private Task&lt;string&gt; GetStringAsync() =&gt; Task.FromResult(&quot;string&quot;);
private Task&lt;int&gt; GetIntAsync() =&gt; Task.FromResult(1);
private Task&lt;List&lt;string&gt;&gt; GetStringListAsync()
    =&gt; Task.FromResult(new List&lt;string&gt; { &quot;string&quot;});
private Task&lt;T&gt; GetGenericAsync&lt;T&gt;(T data) =&gt; Task.FromResult(data);

答案1

得分: 1

简单的答案是编写更多的异步方法;

public async Task ProcessString(){
    var str = await GetStringAsync();
    DoSomething(str);
}

await Task.WhenAll(
    ProcessString(), 
    ProcessInt(),
    ...
);
英文:

The simple answer is to write more async methods;

public async Task ProcessString(){
    var str = await GetStringAsync();
    DoSomething(str);
}

await Task.WhenAll(
    ProcessString(), 
    ProcessInt(),
    ...
);

答案2

得分: 0

最后,对于那些不想使用if/switch的人。我使用了Dictionary<TAsk, Action> 帮助我管理任务和结果。

private async Task CompleteTasksAsync()
{
    var taskA = GetStringAsync();
    var taskB = GetIntAsync();
    var taskC = GetStringListAsync();
    var taskD = GetGenericAsync<double>(1d);

    Dictionary<Task, Action> tasks = new()
    {
        {taskA, () => Console.WriteLine(taskA.Result)},
        {taskB, () => Console.WriteLine(taskB.Result)},
        {taskC, () => Console.WriteLine(taskC.Result)},
        {taskD, () => Console.WriteLine(taskD.Result)}
    };

    while (tasks.Any())
    {
        var completedTask = await Task.WhenAny(tasks.Keys);

        tasks[completedTask]();

        tasks.Remove(completedTask);
    }
}
英文:

Finally, For anyone who want to do it without the if/switch. I used Dictionary&lt;TAsk, Action&gt; and this helped me to shape the tasks and results.

private async Task CompleteTasksAsync()
{
   var taskA = GetStringAsync();
   var taskB = GetIntAsync();
   var taskC = GetStringListAsync();
   var taskD = GetGenericAsync&lt;double&gt;(1d);

   Dictionary&lt;Task, Action&gt; tasks = new()
   {
     {taskA, () =&gt; Console.WriteLine(taskA.Result)},
     {taskB, () =&gt; Console.WriteLine(taskB.Result)  },       {taskC, () =&gt; Console.WriteLine(taskC.Result) },
     {taskD, () =&gt; Console.WriteLine(taskD.Result) }
   };

   while (tasks.Any())
   {
      var completedTask = await Task.WhenAny(tasks.Keys);

      tasks[completedTask]();

      tasks.Remove(completedTask);
  }

}

huangapple
  • 本文由 发表于 2023年2月24日 06:31:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75550987.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定