有什么方法可以等待 ActionBlock 中的所有任务完成?

Any way to wait for all tasks to be complete in ActionBlock?

首先,让我描述一下我正在编写的程序的流程。

GUI 中有一个对象列表,当用户单击一个对象时,对象数据将从磁盘中读取并加载。这可能需要大约 3-4 秒。

假设用户不耐烦,在第一个对象仍在加载时单击了另一个对象。程序将加载第二个对象,同时取消第一个对象的加载。

由于用户可能会在任何加载操作成功完成之前发送垃圾邮件,因此我实现了一个操作块来对所有加载操作进行排队。

所以我有一个这样的动作块:

this.loadObjectActionBlock = new ActionBlock<CaseObject>(
    c => this.LoadCaseData(CaseObject),
    new ExecutionDataflowBlockOptions()
    {
        MaxDegreeOfParallelism = 10,
    });

每次用户点击案例对象时,我都会调用:

this.loadObjectActionBlock.Post(CaseObject);

并且 CaseObject 将由我这样定义的函数处理:

private void LoadCaseData(CaseObject caseObject)
    {
        caseObject.LoadCaseData();          
    }

我现在需要做的是,我需要等到所有 CaseObjects 都加载完毕,然后我才能继续我的代码。

我尝试通过调用

来检测所有案例何时被处理
if (this.loadObjectActionBlock.InputCount == 0)
{
    this.loadObjectActionBlock.Complete();
}

after caseObject.LoadCaseData(); 但这会导致奇怪的结果,因为加载动作发生得太快并且动作块被告知不再接受任何输入。如果我理解正确,InputCount 属性 只查看队列中剩余的作业数。

所以我想做的是像这样等待 ActionBlock:

await this.loadObjectActionBlock.Completion;

当队列中的所有内容都已完全处理时。

我可能没有按预期使用 ActionBlock,因此如果有任何替代方案,请提出任何我可以阅读的建议。

TLDR:我想同时处理多个任务(由用户启动)并等待所有任务完成,然后再执行一个任务。

提前致谢:)

The program will load the second object and at the same time, will cancel the loading for the first object.

队列不是解决此行为的合适方法,尤其是因为 TPL 块只能完成一次。

如果您想实现此行为,只需确保在继续下一个操作之前观察到取消标记:

private static void ProcessCase(CaseObject caseObject, CancellationToken token)
{
  caseObject.LoadCaseData();
  token.ThrowIfCancellationRequested();
  ... // Further processing goes here
}

从 UI 线程调用为:

static CancellationTokenSource _cts;
private static async Task ProcessCaseAsync(CaseObject caseObject)
{
  if (_cts != null)
    _cts.Cancel();
  _cts = new CancellationTokenSource();
  await Task.Run(() => ProcessCase(caseObject, _cts.Token));
}