尝试将Task.WhenAll与Task <string>一起使用不起作用

时间:2020-07-15 10:53:00

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

我正在尝试将多个资源合并到一个集合中(下面的变量)。 GetLocations2返回一个Task,我希望能够将其添加到任务结果集合中(同样是s变量)。但是,由于以下错误,我无法将任务结果添加到集合中:

错误CS1503参数1:无法从“字符串”转换为 'System.Threading.Tasks.Task'

被叫

public static async Task<string> WebRequest2(Uri uri)
{
    using (var client = new WebClient())
    {
        var result = await client.OpenReadTaskAsync(uri).ConfigureAwait(false);

        using (var sr = new StreamReader(result))
        {
            return sr.ReadToEnd();
        }
    }
}

来电者

private static async Task GetLocations2()
{
    var s = new List<Task<string>>();

    foreach (var lob in _lobs)
    {
        var r = await Helper.WebRequest2(new Uri(lob));
  
        var x = Helper.DeserializeResponse<SLICS>(r);

        s.Add(r); //Getting red squiggly here
    }

    //var w = await Task.WhenAll();

}

2 个答案:

答案 0 :(得分:4)

在将任务添加到列表之前,您不需要await,它基本上可以解开Task创建的Helper.WebRequest2(也要等待Task完成,因此任务在您的原始代码将按顺序执行):

private static async Task GetLocations2()
{
    var s = new List<Task<string>>();

    foreach (var lob in _lobs)
    {
        var r = Helper.WebRequest2(new Uri(lob));
  
        // var x = Helper.DeserializeResponse<SLICS>(r); this should be done after Task.WhenAll 
        // or using `ContinueWith`

        s.Add(r); 
    }

    var w = await Task.WhenAll(s);

}

答案 1 :(得分:3)

您还可以将两个操作都包装在async lambda中,以避免必须重复两次:

private static async Task GetLocations2()
{
    IEnumerable<SLICS> w = await Task.WhenAll(_lobs.Select(async lob =>
    {
        var r = await Helper.WebRequest2(new Uri(lob));
        return Helper.DeserializeResponse<SLICS>(r);
    }));
}

使用Select会枚举lambda表达式返回的所有Tasks,然后Task.WhenAll将等待它们全部完成并解开结果。