データベースを呼び出すワーカー メソッドを呼び出しています。このメソッドは反復処理を行い、並列処理のために値を返します。データベースに打撃を与えるのを防ぐために、DB への実行を一時停止する Thread.Sleep があります。ただし、これは Parallel.ForEach でまだ発生している実行をブロックしているようです。ブロックを防ぐためにこれを達成するための最良の方法は何ですか?
private void ProcessWorkItems()
{
_cancellation = new CancellationTokenSource();
_cancellation.Token.Register(() => WorkItemRepository.ResetAbandonedWorkItems());
Task.Factory.StartNew(() =>
Parallel.ForEach(GetWorkItems().AsParallel().WithDegreeOfParallelism(10), workItem =>
{
var x = ItemFactory(workItem);
x.doWork();
}), _cancellation.Token);
}
private IEnumerable<IAnalysisServiceWorkItem> GetWorkItems()
{
while (!_cancellation.IsCancellationRequested)
{
var workItems = WorkItemRepository.GetItemList(); //database call
workItems.ForEach(item =>
{
item.QueueWorkItem(WorkItemRepository);
});
foreach (var item in workItems)
{
yield return item;
}
if (workItems.Count == 0)
{
Thread.Sleep(30000); //sleep this thread for 30 seconds if no work items.
}
}
yield break;
}
編集:回答を含めるように変更しましたが、期待どおりに機能しません。.AsParallel().WithDegreeOfParallelism(10) を GetWorkItems() 呼び出しに追加しました。ベース スレッドがスリープ状態であっても、Parallel は実行し続ける必要があると考えているのですが、私の予想は間違っていますか?
例: 15 個のアイテムがあり、10 個のアイテムを繰り返し取得して開始します。それぞれが終了すると、16 番目の項目を要求するまで、GetWorkItems から別の項目を要求します。その時点で、それ以上のアイテムの取得を停止する必要がありますが、完了するまでアイテム 11 ~ 15 の処理を続行する必要があります。それはどのように並行して機能するべきですか?現在はそれを行っていないためです。現在実行しているのは、6 が完了すると、Parallel.ForEach でまだ実行されている後続の 10 をロックすることです。