[英]How to use task parallel library (TPL) with load balancing and limited degree of parallelism?
我的任務是使用(異步)接口將已知的nr值寫入外部系統。 我必須限制並發執行的最大並行寫入次數。 此外,我必須使用負載平衡,因為該外部系統可能需要更長的時間來寫入某些值。
我知道如何解決這些問題本身:
並行度:
new ParallelOptions {MaxDegreeOfParallelism = maxNrParallelWrites}
我也偶然發現了這篇文章: http : //msdn.microsoft.com/en-us/library/ee789351(v = vs.110).aspx
負載均衡:
var partitioner = Partitioner.Create(values.ToList(), true);
來自異步接口的任務:
var writeTask = Task<AccessResult>.Factory.FromAsync(BeginWriteValue, EndWriteValue, value.SystemId, value.Xml, priority, null);
但是,我如何正確地結合所有這些技術? 我創建了以下代碼:
int maxNrParallelWrites = GetMaxNrParallelWrites();
var partitioner = Partitioner.Create(values.ToList(), true);
Parallel.ForEach(partitioner, new ParallelOptions {MaxDegreeOfParallelism = maxNrParallelWrites},
(val) =>
{
var writeValueTask = GetWriteValueTask(val, priority);
Task.WaitAny(writeValueTask);
});
我特別不確定上一代碼的最后一部分:執行工作負載的操作。 是否更好,而不是創建一個WriteValueTask直接使用這樣的同步接口:
(val) =>
{
var accessResult = externalSystem.WriteValue(....);
}
或者可以創建一個任務然后直接等待它(Task.WaitAny(...))?
您應該使用TPL Dataflow的ActionBlock
來封裝所有這些內容。 這是一個基於actor的框架,是TPL的一部分:
var block = new ActionBlock<Value>(
value => GetWriteValueTask(value, priority)
new ExecutionDataflowBlockOptions()
{
MaxDegreeOfParallelism = GetMaxNrParallelWrites();
});
foreach (var value in values)
{
block.Post(value);
}
您可以設置MaxDegreeOfParallelism
, BoundedCapacity
和負載均衡,因為它一次只處理MaxDegreeOfParallelism
項目,每次完成時它處理下一個項目(而不是使用預先分區集合的Partitioner
程序)
注意:當您執行async
任務並等待它同步完成時(即Task.WaitAny
)實際上沒有任何異步。 在這種情況下,你應該使用Task.WhenAny
。
本文中有一個很好的示例,說明如何創建負載平衡ForEachASync
方法。 。 我已經取出Task.Run
以避免啟動新線程,然后擴展方法變為:
public static class Extensions
{
public static async Task ExecuteInPartition<T>(IEnumerator<T> partition, Func<T, Task> body)
{
using (partition)
while (partition.MoveNext())
await body(partition.Current);
}
public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
return Task.WhenAll(
from partition in Partitioner.Create(source).GetPartitions(dop)
select ExecuteInPartition(partition, body));
}
}
用法
此示例一次異步處理最多100封電子郵件
// Process 100 emails at a time
return emailsToProcess.ForEachAsync(100, ProcessSingleEmail);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.