在foreach循环中使用asyn await

时间:2015-06-01 21:00:48

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

在foreach循环中使用asyc await是不正确的吗?我收到WebException,请求被取消了。

以下是我正在处理的代码的概述。如果不清楚,请告诉我。

using (var client = new HttpClient())
{
    client.BaseAddress = new Uri("https://xxx.xxx.com/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    try
    {
        var response = await client.PostAsJsonAsync("customers/xxxx/xxx/documents", requestMessage);

        response.EnsureSuccessStatusCode();
        var returnValue = response.Content.ReadAsAsync<ResponseMessage>();

        var hasDocuments = returnValue.Result.SearchResults.Any();

        if (hasDocuments)
        {
            // HTTP GET
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));

            returnValue.Result.SearchResults.ForEach(async d =>
            {
                response = await client.GetAsync(d.Self + ".pdf");
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }
}

1 个答案:

答案 0 :(得分:7)

您没有在foreach循环中使用async / await,而是使用as {/等待List<T>.ForEach(Action<T>)。由于ForEach仅接受Action<T>(void返回类型),因此ForEach(async d => { ... }作为async void函数进行处理,因为这是将Action<T>传递为foreach的唯一方式{1}}。这使得ForEach不会等到上一个项目完成后再转移到下一个项目,这就是导致错误的原因。

使用普通List<T>.ForEach代替 if (hasDocuments) { // HTTP GET client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*")); foreach (var d in returnValue.Result.SearchResults) { response = await client.GetAsync(d.Self + ".pdf"); }; } 方法,它应该可以正常工作。

async d => ...

您被允许使用Func<T,Task>的唯一时间是您传入的函数接收IdInstanceTag int, APPROVED_TIME timestamp, ModifiedTime date, DATE_TO date, DEFINITION XML, ID int, CreatedBy varchar(100), ModifiedBy varchar(100) 时的情况(请参阅Task.Run)。