Ton*_*ony 2 c# asynchronous async-await
我有一个应用程序,通常有1.000 - 30.000文件转换一些数据.
我需要做3个步骤:
所以这三个步骤包括一些I/O,我使用了async/await方法:
var tasks = files.Select(async (file) =>
{
Item item = await createtempFile(file).ConfigureAwait(false);
await convert(item).ConfigureAwait(false);
await clean(item).ConfigureAwait(false);
}).ToList();
await Task.WhenAll(tasks).ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)
我不知道这是否是最好的做法,因为我创造了超过一千个任务.我想过将这三个步骤拆分为:
List<Item> items = new List<Item>();
var tasks = files.Select(async (file) =>
{
Item item = await createtempFile(file, ext).ConfigureAwait(false);
lock(items)
items.Add(item);
}).ToList();
await Task.WhenAll(tasks).ConfigureAwait(false);
var tasks = items.Select(async (item) =>
{
await convert(item, baseAddress, ext).ConfigureAwait(false);
}).ToList();
await Task.WhenAll(tasks).ConfigureAwait(false);
var tasks = items.Select(async (item) =>
{
await clean(targetFile, item.Doctype, ext).ConfigureAwait(false);
}).ToList();
await Task.WhenAll(tasks).ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)
但这似乎没有更好或更快,因为我创造了数千次任务.
我应该限制任务的创建吗?像100个任务的大块?或者我只是过度思考它,创造成千上万的任务就好了.
CPU处于空闲状态,峰值为2-4%,因此我想到了太多的等待或上下文切换.
也许WebRequest调用太多,因为WebServer/WebService不能同时处理数千个请求,我应该只限制WebRequests?
我已经在app.config文件中增加了.NET maxconnection.
小智 9
可以并行执行异步操作,限制并发操作的数量.有一个很酷的扩展方法,它不是.Net框架的一部分.
/// <summary>
/// Enumerates a collection in parallel and calls an async method on each item. Useful for making
/// parallel async calls, e.g. independent web requests when the degree of parallelism needs to be
/// limited.
/// </summary>
public static Task ForEachAsync<T>(this IEnumerable<T> source, int degreeOfParalellism, Func<T, Task> action)
{
return Task.WhenAll(Partitioner.Create(source).GetPartitions(degreeOfParalellism).Select(partition => Task.Run(async () =>
{
using (partition)
while (partition.MoveNext())
await action(partition.Current);
})));
}
Run Code Online (Sandbox Code Playgroud)
像这样称呼它:
var files = new List<string> {"one", "two", "three"};
await files.ForEachAsync(5, async file =>
{
// do async stuff here with the file
await Task.Delay(1000);
});
Run Code Online (Sandbox Code Playgroud)
正如评论者正确指出的那样,你想多了。.NET 运行时在跟踪数千个任务时绝对没有问题。
但是,您可能需要考虑使用 TPL 数据流管道,这将使您能够轻松地为管道中的不同操作(“块”)设置不同的并发级别。