简体   繁体   English

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

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

First of all, let me describe the flow of the program I am writing. 首先,让我描述一下我正在编写的程序的流程。

There is a list of objects in the GUI and when the user clicks on one, the object data is read from the disk and is loaded. GUI中有一个对象列表,当用户单击一个对象列表时,将从磁盘读取对象数据并进行加载。 This could take around 3-4 seconds. 这可能需要3-4秒。

Let's say the user is impatient and clicks on another object while the first one is still loading. 假设用户不耐烦,并且在第一个对象仍在加载时单击了另一个对象。 The program will load the second object and at the same time, will cancel the loading for the first object. 该程序将加载第二个对象,同时取消第一个对象的加载。

As the user could spam load operations before any of them could complete successfully, I have implemented an action block to queue up all the load operations. 由于用户可以在垃圾邮件加载操作无法成功完成之前对其进行垃圾邮件处理,因此我实现了一个动作块来对所有加载操作进行排队。

So I have an action block like this: 所以我有一个这样的动作块:

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

Every time the user has clicked on a Case Object, I will call: 每次用户单击Case对象时,我都会调用:

this.loadObjectActionBlock.Post(CaseObject);

And the CaseObject will be processed by a function I have defined like this: CaseObject将由我这样定义的函数处理:

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

What I need to do right now is, I need to wait until ALL CaseObjects are loaded so that I could continue my code after that. 我现在需要做的是,我需要等到所有CaseObjects加载完毕后,才能继续执行我的代码。

I have tried detecting when all cases are processed by calling 我试图通过调用来检测何时处理所有案件

if (this.loadObjectActionBlock.InputCount == 0)
{
    this.loadObjectActionBlock.Complete();
}

after caseObject.LoadCaseData(); caseObject.LoadCaseData(); but this leads to strange results when load actions happen way too fast and the action block is told not to accept any more inputs. 但这会导致奇怪的结果,即加载操作发生得太快并且告诉操作块不要接受更多输入。 If I understand correctly, the InputCount property only looks at the number of jobs left in the queue. 如果我理解正确, InputCount属性仅查看队列中剩余的作业数。

So what I'd like to do is I'd like to await the ActionBlock like: 所以我想做的就是等待ActionBlock之类的:

await this.loadObjectActionBlock.Completion;

when everything in the queue has been fully processed. 当队列中的所有内容均已完全处理时。

I may not be using the ActionBlock as it is intended to, so if there are any alternatives on this, please kindly suggest anything that I could read up on. 我可能未按预期使用ActionBlock,因此,如果对此有任何选择,请提出我可以阅读的任何内容。

TLDR: I'd like to process multiple tasks (started by user) concurrently and wait for all to be complete then followed by a single task. TLDR:我想同时处理多个任务(由用户启动),并等待所有任务完成,然后再执行单个任务。

Thanks in advance :) 提前致谢 :)

The program will load the second object and at the same time, will cancel the loading for the first object. 该程序将加载第二个对象,同时取消第一个对象的加载。

A queue is not the appropriate solution for this behavior, especially since a TPL block can only be completed once. 队列不是解决此问题的适当方法,特别是因为TPL块只能完成一次。

If you want to implement this behavior, simply ensure the cancellation token is observed before continuing with the next operation: 如果要实现此行为,只需确保已观察到取消令牌,然后再继续执行下一个操作:

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

Called from the UI thread as: 从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));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM