有什么方法可以等待 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));
}
首先,让我描述一下我正在编写的程序的流程。
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));
}