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

C# TPL: Invoke method on outer scoped instance

所以我的标题相当晦涩,这就是我担心的地方。 我能否在块外声明的 class 实例上调用方法而不会遇到陷阱

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

HeavyLifter hl = new HeavyLifter();

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

我的担忧来源如下。

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

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

非常感谢任何帮助,我并不太迷茫,但我知道并发是潜在错误和极端情况的王者。

  1. 假设帧指针是指堆栈帧,那么是的,每次调用都有自己的堆栈帧和相关变量。如果函数的参数是引用类型,那么所有参数都将引用同一个对象。
  2. 对所有调用使用相同的 HeavyLifter 实例是否安全取决于 DoSomeHeavyLifting 方法是否有副作用。也就是说,DoSomeHeavyLifting 是否修改了 HeavyLifter 对象状态的任何内容。 (或任何其他引用的对象)

最终这样做是否安全很大程度上取决于 DoSomeHeavyLifting 内部所做的事情。如果它经过精心构造以成为 reentrant 那么按照您的方式调用它就没有问题。但是,如果 DoSomeHeavyLifting 修改了状态,或者状态被修改为任何其他操作的副作用,那么必须在整体架构的上下文中决定如何处理它。例如,您是允许状态更改并强制执行原子性,还是阻止任何影响操作的状态更改?在不知道该方法实际做什么的情况下,不可能给出任何具体的建议。

一般来说,在为并发设计时最好假设最坏的情况:

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