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)
.....
});
我的担忧来源如下。
Block可能同时有多个线程运行,这些线程中的每一个都可能进入DoSomeHeavyLifting方法。每个函数调用都有自己的帧指针吗?我是否应该确保不引用 CountWords 范围之外的任何变量?
有比在我的块中实例化 HeavyLifter 更好的方法吗?
非常感谢任何帮助,我并不太迷茫,但我知道并发是潜在错误和极端情况的王者。
- 假设帧指针是指堆栈帧,那么是的,每次调用都有自己的堆栈帧和相关变量。如果函数的参数是引用类型,那么所有参数都将引用同一个对象。
- 对所有调用使用相同的
HeavyLifter
实例是否安全取决于 DoSomeHeavyLifting
方法是否有副作用。也就是说,DoSomeHeavyLifting
是否修改了 HeavyLifter
对象状态的任何内容。 (或任何其他引用的对象)
最终这样做是否安全很大程度上取决于 DoSomeHeavyLifting
内部所做的事情。如果它经过精心构造以成为 reentrant 那么按照您的方式调用它就没有问题。但是,如果 DoSomeHeavyLifting
修改了状态,或者状态被修改为任何其他操作的副作用,那么必须在整体架构的上下文中决定如何处理它。例如,您是允许状态更改并强制执行原子性,还是阻止任何影响操作的状态更改?在不知道该方法实际做什么的情况下,不可能给出任何具体的建议。
一般来说,在为并发设计时最好假设最坏的情况:
- 如果竞争条件可能发生,它就会发生。
- 当出现竞争条件时,您将以代码允许的最复杂方式输掉比赛。
- 非原子状态更新会相互破坏,并使您的对象处于未定义状态。
- 如果你使用锁,就会出现死锁的情况。
- 在调试中永远不会发生的事情,总会在发布中发生。
所以我的标题相当晦涩,这就是我担心的地方。 我能否在块外声明的 class 实例上调用方法而不会遇到陷阱 即
结构如下的代码是否存在并发问题。
HeavyLifter hl = new HeavyLifter();
var someActionBlock = new ActionBlock<string>(n =>
{
int liftedStuff= hl.DoSomeHeavyLifting(n);
if (liftedStuff> 0)
.....
});
我的担忧来源如下。
Block可能同时有多个线程运行,这些线程中的每一个都可能进入DoSomeHeavyLifting方法。每个函数调用都有自己的帧指针吗?我是否应该确保不引用 CountWords 范围之外的任何变量?
有比在我的块中实例化 HeavyLifter 更好的方法吗?
非常感谢任何帮助,我并不太迷茫,但我知道并发是潜在错误和极端情况的王者。
- 假设帧指针是指堆栈帧,那么是的,每次调用都有自己的堆栈帧和相关变量。如果函数的参数是引用类型,那么所有参数都将引用同一个对象。
- 对所有调用使用相同的
HeavyLifter
实例是否安全取决于DoSomeHeavyLifting
方法是否有副作用。也就是说,DoSomeHeavyLifting
是否修改了HeavyLifter
对象状态的任何内容。 (或任何其他引用的对象)
最终这样做是否安全很大程度上取决于 DoSomeHeavyLifting
内部所做的事情。如果它经过精心构造以成为 reentrant 那么按照您的方式调用它就没有问题。但是,如果 DoSomeHeavyLifting
修改了状态,或者状态被修改为任何其他操作的副作用,那么必须在整体架构的上下文中决定如何处理它。例如,您是允许状态更改并强制执行原子性,还是阻止任何影响操作的状态更改?在不知道该方法实际做什么的情况下,不可能给出任何具体的建议。
一般来说,在为并发设计时最好假设最坏的情况:
- 如果竞争条件可能发生,它就会发生。
- 当出现竞争条件时,您将以代码允许的最复杂方式输掉比赛。
- 非原子状态更新会相互破坏,并使您的对象处于未定义状态。
- 如果你使用锁,就会出现死锁的情况。
- 在调试中永远不会发生的事情,总会在发布中发生。