【问题标题】:using TPL ActionBlock, Can I add a new item after the job completed使用 TPL ActionBlock,我可以在作业完成后添加一个新项目吗
【发布时间】:2020-05-19 10:29:53
【问题描述】:

我在我的应用程序中使用 TPL ActionBlock 来实现并行性。

我有一个应用程序将根据用户输入执行操作。根据输入,有时该操作需要更多时间,有时则不需要。

所以ActionBlock 的真正目的是每当输入出现时,我想首先在 UI 中显示它(有一个窗口),然后在后台执行操作。所以这个想法就像来自用户的任何东西,在 UI 中显示并在后台并行执行。

现在,在 UI(窗口)中,我有一个停止按钮来停止用户输入。每当我单击此功能时,用户将无法再输入任何内容。现在我也调用ActionBlock.Complete 方法来检查队列/块是否完成。

所以我的疑问是,

我调用ActionBlock.Complete() 作为基于停止按钮单击的单独方法,它将等待作业完成然后做一些工作并关闭用户界面。这真的是个好主意吗,或者我必须在构造函数中调用ActionBlock.Complete(),或者在定义ActionBlock的位置调用。

public void CheckJobQ()
{
    _jobs.Complete();
    _jobs.Completion.Wait();
}

_jobsActionBlock

var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions()
{
    MaxDegreeOfParallelism = 100
};
_jobs = new ActionBlock<Tuple<Action<Element>, Element>>((job) =>
{
    job.Item1.Invoke(job.Item2);
}, executionDataflowBlockOptions);

【问题讨论】:

  • “向数据流块发出信号它不应再接受或产生任何消息并且不应再消耗任何延迟的消息。” - ActionBlock&lt;TInput&gt;.Complete() - 为什么你认为在ctor中完成它是一个选项?
  • 还有:问题文本如何与标题匹配?你想解决什么问题?
  • 这里还有一个疑问,如果我的ActionBlock在call_jobs.completion.Wait()之后完成了,我将如何再次启动一个新的ActionBlock。有没有可能。
  • 当状态机处于其最终状态(“已完成”)时,它无法重置,afaik。您需要创建一个新实例。

标签: c# asynchronous task-parallel-library tpl-dataflow


【解决方案1】:

所有数据流块都是线程安全的,所以调用:

_jobs.Complete();

...来自ActionBlock 的操作是允许的,完全没问题。

另一方面,数据流块不是死锁安全的。因此,如果您在处理元素时等待块的完成:

_jobs.Completion.Wait();

...你可能已经开枪打中了自己的脚。动作永远不会完成,块本身也不会。

【讨论】:

  • 是的,我不会使用不存在的“死锁安全”一词(我明白你的意思)
猜你喜欢
  • 1970-01-01
  • 2019-09-02
  • 1970-01-01
  • 2016-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
  • 2019-12-20
相关资源
最近更新 更多