在ActionBlock中等待所有任务完成的任何方式

本文关键字:任何方 何方 ActionBlock 等待 任务 | 更新日期: 2023-09-27 18:18:56

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

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

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

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

我有一个这样的动作块:

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

每当用户点击一个Case Object时,我将调用:

this.loadObjectActionBlock.Post(CaseObject);

CaseObject将由我定义的函数处理,如下所示:

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

我现在需要做的是,我需要等到所有的CaseObjects被加载,这样我就可以在那之后继续我的代码。

我已经尝试通过调用

来检测何时所有情况都已处理。
if (this.loadObjectActionBlock.InputCount == 0)
{
    this.loadObjectActionBlock.Complete();
}

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

那么我要做的就是等待ActionBlock,比如:

await this.loadObjectActionBlock.Completion;

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

我可能没有按照预期使用ActionBlock,所以如果有任何替代方案,请建议我可以阅读的任何内容。

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

提前感谢:)

在ActionBlock中等待所有任务完成的任何方式

程序将加载第二个对象,同时取消第一个对象的加载。

对于这种行为,队列不是合适的解决方案,特别是因为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));
}