【问题标题】:Transform IEnumerable<Task<T>> asynchronously by awaiting each task通过等待每个任务异步转换 IEnumerable<Task<T>>
【发布时间】:2013-04-26 18:29:08
【问题描述】:

今天我想知道如何通过等待每个任务来转换任务列表。 考虑以下示例:

private static void Main(string[] args)
{
    try
    {
        Run(args);                
        Console.ReadLine();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
        Console.ReadLine();
    }
}

static async Task Run(string[] args)
{
    //Version 1: does compile, but ugly and List<T> overhead
    var tasks1 = GetTasks();                       

    List<string> gainStrings1 = new List<string>();
    foreach (Task<string> task in tasks1)
    {
        gainStrings1.Add(await task);
    }
    Console.WriteLine(string.Join("", gainStrings1));

    //Version 2: does not compile
    var tasks2 = GetTasks();
    IEnumerable<string> gainStrings2 = tasks2.Select(async t => await t);
    Console.WriteLine(string.Join("", gainStrings2));
}

static IEnumerable<Task<string>> GetTasks()
{
    string[] messages = new[] { "Hello", " ", "async", " ", "World" };

    for (int i = 0; i < messages.Length; i++)
    {
        TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
        tcs.SetResult(messages[i]);
        yield return tcs.Task;
    }
}

我想在没有 foreach 的情况下转换我的任务列表,但是无论是匿名函数语法还是通常的函数语法都允许我做我的 foreach 所做的事情。

我是否必须依赖我的 foreach 和 List&lt;T&gt; 或者有什么方法可以让它与 IEnumerable&lt;T&gt; 一起使用以及它的所有优势?

【问题讨论】:

  • 为什么第二个不编译?错误信息是什么?如果在Select 之后添加缺少的ToList(),它会编译吗?
  • 因为它返回IEnumerable&lt;Task&lt;string&gt;&gt;

标签: c# linq task-parallel-library async-await


【解决方案1】:

这个呢:

await Task.WhenAll(tasks1);
var gainStrings = tasks1.Select(t => t.Result).ToList();

等待所有任务结束,然后提取结果。如果您不关心它们的完成顺序,这是理想的选择。

编辑2: 更好的方法:

var gainStrings = await Task.WhenAll(tasks1);

【讨论】:

  • 你可以使用WhenAll的返回值,而不是Select,它将是每个任务所有结果的string[]
  • 据此:msdn.microsoft.com/en-us/library/hh194874.aspx 只有给它一个数组,它才会这样做。
  • 你不需要ToArray()Task.WhenAll() 也适用于IEnumerable&lt;Task&lt;T&gt;&gt;
  • Nope。即使您传入IEnumerable&lt;Task&lt;TResult&gt;&gt;,它也会返回一个结果数组
  • EDIT2 更好,因为有时 Visual Studio 会发出有关在任务上调用 .Result 的警告。
猜你喜欢
  • 1970-01-01
  • 2015-12-22
  • 1970-01-01
  • 1970-01-01
  • 2014-06-11
  • 1970-01-01
相关资源
最近更新 更多