我正在调用一个工作方法,该方法调用数据库,然后迭代并产生返回值以进行并行处理。为了防止它破坏数据库,我在那里有一个 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 个项目并启动它们。每个完成后,它都会从 GetWorkItems 请求另一个,直到它尝试请求第 16 个项目。此时,它应该停止尝试抓取更多项目,但应该继续处理项目 11-15,直到这些项目完成。并行应该如何工作?因为它目前没有这样做。它目前正在做的是当它完成 6 时,它锁定后续 10 仍然在 Parallel.ForEach 中运行。