Dispatcher,Async / Await,Concurrent work

时间:2016-07-22 08:05:22

标签: c# multithreading parallel-processing async-await dispatcher

我有一堆异步方法,我从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()创建单独的线程。你能给我一些提示怎么做吗?

2 个答案:

答案 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);
    }