C#TPL:在外部作用域实例上调用方法

时间:2015-09-08 17:16:36

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

所以我的头衔相当模糊,这就是我所担心的。 我是否可以在块的外部声明的类的实例上调用方法而不会遇到陷阱,即

以下结构化的代码是否存在并发问题。

HeavyLifter hl = new HeavyLifter();

var someActionBlock = new ActionBlock<string>(n =>
{
   int liftedStuff= hl.DoSomeHeavyLifting(n);
   if (liftedStuff> 0)
   .....
});

我关注的来源如下。

  1. Block可能同时运行多个线程,并且每个线程都可以进入DoSomeHeavyLifting方法。每个函数调用都有自己的帧指针吗?我是否应该确保我没有引用CountWords范围之外的任何变量?

  2. 有没有比在我的区块中实例化HeavyLifter更好的方法?

  3. 非常感谢任何帮助,我不会丢失,但我知道并发是潜在错误和角落案件之王。

1 个答案:

答案 0 :(得分:2)

  1. 假设通过帧指针,你的意思是堆栈帧,然后是,每个调用获得它自己的堆栈帧和相关的变量。如果函数的参数是引用类型,则所有参数都将引用相同的对象。
  2. 对所有调用使用相同的HeavyLifter实例是否安全取决于DoSomeHeavyLifting方法是否有副作用。也就是说,DoSomeHeavyLifting是否修改了HeavyLifter对象状态的任何内容。 (或任何其他引用的对象)
  3. 最终这样做是否安全在很大程度上取决于DoSomeHeavyLifting内部的作用。如果它是为了reentrant而精心构造的,那么就可以按照它的方式调用它。但是,如果DoSomeHeavyLifting修改状态,或者状态被修改为任何其他操作的副作用,那么必须在整体架构的上下文中决定如何处理它。例如,您是允许状态更改,强制执行原子性,还是阻止任何影响操作的状态更改?在不知道方法实际在做什么的情况下,不可能给出任何具体的建议。

    通常,在设计并发时,通常最好假设最坏的情况:

    • 如果发生竞争条件,就会发生。
    • 当竞争条件发生时,您将以代码允许的最复杂方式输掉比赛。
    • 非原子状态更新将相互损坏,并使您的对象处于未定义状态。
    • 如果您使用锁定,则会出现导致死锁的情况。
    • 在调试中永远不会发生的事情总会在发布中发生。