如何使公共属性线程安全?

TX_*_*TX_ 2 .net c# multithreading thread-safety

BackgroundWorker出于某种原因正在实施替换,我必须实现以下公共属性:

public bool CancellationPending { get; private set; }
public bool IsBusy { get; private set; }
public bool WorkerReportsProgress { get; set; }
public bool WorkerSupportsCancellation { get; set; }
Run Code Online (Sandbox Code Playgroud)

我相信你知道他们服务的目的是什么BackgroundWorker.所以它们可能被不同的线程访问/修改.我担心如何为多线程"保护"它们.我认为声明它们volatile就足够了,但volatile不能应用于自动属性.

我该怎么办?我应该为这些属性创建私有字段,并声明它们volatile吗?或者我lock应该在每个内部使用getset阻止?

我认为这应该是非常常见的情况 - 使属性(最好是自动属性)线程安全.请注意,在此示例中,所有属性都是原子类型.

编辑:

澄清我需要的东西:我需要确保所有线程始终读取属性的最新值.请参阅:https://stackoverflow.com/a/10797326/1081467

所以再一次,你建议使用volatile,或者lock其他什么吗?..当使用bool属性时,保证原子性,所以只留下第二个问题(读取最新值),那么如何正确地解决这个问题?当你拥有非原始类型的属性时呢?你把lockS IN每个getset块?

TX_*_*TX_ 6

我想出了以下实现.请评论您是否认为它是最佳解决方案:

//========== Public properties ==================================================//

public bool CancellationPending { get { return _cancellationPending; } private set { _cancellationPending = value; } }

public bool IsBusy { get { return _isBusy; } private set { _isBusy = value; } }

public bool WorkerReportsProgress { get { return _workerReportsProgress; } set { _workerReportsProgress = value; } }

public bool WorkerSupportsCancellation { get { return _workerSupportsCancellation; } set { _workerSupportsCancellation = value; } }

//========== Private fields ==================================================//

private volatile bool _cancellationPending;
private volatile bool _isBusy;
private volatile bool _workerReportsProgress;
private volatile bool _workerSupportsCancellation;
Run Code Online (Sandbox Code Playgroud)

推理:原子性由字段是类型的事实确保bool,因此不需要lock.制作它们volatile将确保任何线程将读取当前值 - 而不是缓存 - 以防另一个线程修改它.我认为这是volatile关键字的确切目的(也是唯一有效的用途),对吧?

  • 这很有趣,因为是你在浪费我的时间,兄弟.即使我100%肯定,你的话让我很怀疑,我决定再次测试.我写了那个能够清楚地说明问题的小代码.我正在使用VS2012,虽然我已经使用VS2010测试过并且行为完全相同.在Visual C#中创建新的空项目.复制/粘贴代码.构建`release`构建,这很重要!然后在调试器外面运行它**,这也很重要!您将看到原始代码在写入"WAITING ..."后会挂起,如果您将`_stop`字段设置为volatile,它将起作用. (4认同)
  • TX是对的,代码挂了.我在生产中得到了同样的问题,我依靠bool属性来使处理循环停止.现在我完全切换到CancellationTokenSource,从实现可靠的取消中获取了大量的实现细节. (2认同)