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。 –