我有一个选定的 contentIds 列表,对于每个内容 ID,我需要调用一个 api,获取响应,然后将收到的每个内容的响应保存在 DB 中。
一次用户可以选择 1-1000 之间的任意数量的内容,并且可以在从 api 获得响应后传递它以更新内容数据库详细信息。
在这种情况下,我最终会为每个内容创建多个请求。
我想继续进行asp.net async Task操作,然后编写了以下方法。
我编写的代码目前为每个 contentId 创建一个任务,最后我正在等待所有任务获得响应。
public static Task<KeyValuePair<int, string>> GetXXXApiResponse(string url, int contentId)
{
var client = new HttpClient();
return client.GetAsync(url).ContinueWith(task =>
{
var response = task.Result;
var strTask = response.Content.ReadAsStringAsync();
strTask.Wait();
var strResponse = strTask.Result;
return new KeyValuePair<int, string>(contentId, strResponse);
});
}
我现在正在考虑为我创建的每个任务创建一个线程,反过来,由于工作线程的数量有限,这种方法最终将占用所有线程,这是我不希望发生的。
任何人都可以帮助/指导我如何有效地处理这种情况,即处理多个 api 请求或使用异步任务等进行批处理吗?
仅供引用:我正在使用 .NET 框架 4.5
最佳答案
任务只是可以等待和取消的异步操作的表示。创建新任务不一定会创建新线程(大多数情况下不会)。如果您正确使用 async-await
,您在大多数异步操作期间甚至都没有线程。
但是,同时发出许多请求仍然是有问题的(例如给内容服务器带来太多负担)。所以你可能仍然想使用 SemaphoreSlim
或 TPL Dataflow
限制并发调用的数量:
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(100);
public static async Task<KeyValuePair<int, string>> GetXXXApiResponse(string url, int contentId)
{
await _semaphore.WaitAsync();
try
{
var client = new HttpClient();
var response = await client.GetAsync(url);
var strResponse = await response.Content.ReadAsStringAsync();
return new KeyValuePair<int, string>(contentId, strResponse);
}
finally
{
_semaphore.Release();
}
}
要等待这些任务完成,您应该使用
Task.WhenAll
异步等待而不是 Task.WaitAll
阻塞调用线程:await Task.WhenAll(apiResponses);
关于c# - 如何在ASP.NET中使用Task处理多个请求的批处理?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25288642/