在 foreach 循环中使用异步等待
Using asyn await in foreach loop
在 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;
}
}
您没有在 foreach
循环中使用 async/await,而是在 List<T>.ForEach(Action<T>)
中使用 async/await。因为 ForEach
只接受 Action<T>
(void return 类型)你的 ForEach(async d => { ... }
被作为 async void
函数处理,因为这是它被传递的唯一方法作为 Action<T>
。这使得 ForEach 在移动到下一个项目之前不会等待上一个项目完成,这就是导致错误的原因。
使用普通的 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>
时(参见 Task.Run
作为示例)。
在 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;
}
}
您没有在 foreach
循环中使用 async/await,而是在 List<T>.ForEach(Action<T>)
中使用 async/await。因为 ForEach
只接受 Action<T>
(void return 类型)你的 ForEach(async d => { ... }
被作为 async void
函数处理,因为这是它被传递的唯一方法作为 Action<T>
。这使得 ForEach 在移动到下一个项目之前不会等待上一个项目完成,这就是导致错误的原因。
使用普通的 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>
时(参见 Task.Run
作为示例)。