我在我的应用程序中使用TPL ActionBlock
来实现并行性。
我有一个将根据用户输入执行操作的应用程序。根据输入,有时该操作需要更多时间,而有时则不需要。
所以ActionBlock
的真正目的是,每当有输入输入时,我都想先在UI中显示它(有一个窗口),然后在后台执行操作。因此,这个想法就像来自用户的任何东西一样,在用户界面中显示它并在后台并行执行操作。
现在,在UI(窗口)中,我有一个停止按钮来停止用户输入。每当我单击此功能时,用户将无法再输入任何内容。现在,我还要调用ActionBlock.Complete
方法来检查队列/块是否完成。
所以这是我的疑问,
我正在按[停止]按钮作为单独的方法来调用ActionBlock.Complete()
,它将等待作业完成,然后做一些工作并关闭UI。这真的是个好主意吗,还是我必须在构造函数内部或定义了ActionBlock.Complete()
的地方调用ActionBlock
。
public void CheckJobQ()
{
_jobs.Complete();
_jobs.Completion.Wait();
}
并且_jobs
是ActionBlock
:
var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions()
{
MaxDegreeOfParallelism = 100
};
_jobs = new ActionBlock<Tuple<Action<Element>, Element>>((job) =>
{
job.Item1.Invoke(job.Item2);
}, executionDataflowBlockOptions);
所有数据流块都是线程安全的,因此调用:
_jobs.Complete();
...从ActionBlock
的动作中是允许的,完全没问题。
另一方面,数据流块不是死锁安全的。因此,如果您在处理元素时等待块的完成:
_jobs.Completion.Wait();
...您可能已经把自己开了枪。该操作将永远不会完成,该块本身也不会完成。