2
非常大量的任务,我使用下面的模式来进行大量的操作(可能有数百万)处理内存
var allTasks = new List<Task>();
var throttler = new SemaphoreSlim(initialCount: 8);
foreach (var file in filesToUpload)
{
await throttler.WaitAsync();
allTasks.Add(
Task.Run(async() =>
{
try
{
await UploadFileAsync(file)
}
finally
{
throttler.Release();
}
}));
}
await Task.WhenAll(allTasks);
但是我很担心在累积Task
对象数量巨大allTasks
集合。从一些诊断运行中,我似乎已经建立了大约1Gb的内存用于〜100k个对象。
对上述模式可以做出任何改变来淘汰完成的任务,但仍然保留整体模式的节流效果吗?
我能想到的唯一事情就是对整个数据集进行分区/分批处理,以便上面的代码只能运行,例如, 1000个元素。这是最合适的方法吗?
UPDATE
所以,根据你的咨询亨克,我已经实现了以下内容:
var uploadFileBlock = new ActionBlock<string>(async file =>
{
await UploadFileAsync(file)
}, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 8 });
foreach (var file in filePaths)
{
await uploadFileBlock.SendAsync(file);
}
uploadFileBlock.Completion.Wait();
这似乎做工精细,并有一个相对较低的内存配置文件中的全部时间。这个实现对你来说看起来好吗?
不是一个具体的答案,但一)Task.WhenAll()保留一切记忆和b)你做了Task.Run (异步无效...)做一些异步I/O。使用不必要的线程。 –
[consensus](https://stackoverflow.com/a/11565531/60761)是使用TPL Dataflow。还请阅读下面的答案。 –
由于Add()调用,代码在内存中保存了很多任务。尽管100K-8个任务已经完成,但并不是非常有用。无Clear()也可见。考虑用CountdownEvent类来计算任务,而不是WhenAll。 –