我有一堆异步方法,我从Dispatcher调用它。这些方法不在后台执行任何工作,只是等待一些I / O操作,或等待来自Web服务器的响应。
async Task FetchAsync()
{
// Prepare request in UI thread
var response = await new WebClient().DownloadDataTaskAsync();
// Process response in UI thread
}
现在,我希望通过并行调用多个FetchAsync()
并执行一些最大并行度来执行负载测试。
我的第一次尝试是使用Paralell.Foreach()
,但id与async / await不兼容。
var option = new ParallelOptions {MaxDegreeOfParallelism = 10};
Parallel.ForEach(UnitsOfWork, uow => uow.FetchAsync().Wait());
我一直在寻找被动扩展,但我仍然无法利用Dispatcher和async / await。
我的目标是不为每个FetchAsync()
创建单独的线程。你能给我一些提示怎么做吗?
答案 0 :(得分:2)
只需在不等待每次通话的情况下拨打Fetchasync
,然后使用Task.WhenAll
等待所有通话。
var tasks = new List<Task>();
var max = 10;
for(int i = 0; i < max; i++)
{
tasks.Add(FetchAsync());
}
await Task.WhenAll(tasks);
答案 1 :(得分:0)
以下是针对您的问题的通用可重用解决方案,您不仅可以重复使用FetchAsync方法,还可以重用具有相同签名的任何异步方法。 api还包括实时并发限制支持:
参数不言自明: totalRequestCount:总共需要多少异步请求(FatchAsync调用),async处理器是FetchAsync方法本身,maxDegreeOfParallelism是可选的可空参数。如果要使用最大并发异步请求数进行实时并发限制,请设置它,否则不设置。
public static Task ForEachAsync(
int totalRequestCount,
Func<Task> asyncProcessor,
int? maxDegreeOfParallelism = null)
{
IEnumerable<Task> tasks;
if (maxDegreeOfParallelism != null)
{
SemaphoreSlim throttler = new SemaphoreSlim(maxDegreeOfParallelism.Value, maxDegreeOfParallelism.Value);
tasks = Enumerable.Range(0, totalRequestCount).Select(async requestNumber =>
{
await throttler.WaitAsync();
try
{
await asyncProcessor().ConfigureAwait(false);
}
finally
{
throttler.Release();
}
});
}
else
{
tasks = Enumerable.Range(0, totalRequestCount).Select(requestNumber => asyncProcessor());
}
return Task.WhenAll(tasks);
}