取消 BackgroundWorker 操作的方法是调用 BackgroundWorker.CancelAsync()
:
// RUNNING IN UI THREAD
private void cancelButton_Click(object sender, EventArgs e)
{
backgroundWorker.CancelAsync();
}
在 BackgroundWorker.DoWork 事件处理程序中,我们检查 BackgroundWorker.CancellationPending
:
// RUNNING IN WORKER THREAD
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (!backgroundWorker.CancellationPending) {
DoSomething();
}
}
上面的想法遍布整个网络,包括the MSDN page for BackgroundWorker。 .
现在,我的问题是:这到底有多线程安全?
我查看了 ILSpy 中的 BackgroundWorker 类 — CancelAsync()
只是在不使用内存屏障的情况下将 cancellationPending 设置为 true,而 CancellationPending
只是在不使用内存屏障的情况下返回 cancellationPending内存屏障。
根据 this Jon Skeet page ,上面的代码不是线程安全的。但是the documentation for BackgroundWorker.CancellationPending说,“这个属性是供工作线程使用的,它应该定期检查 CancellationPending 并在它设置为 true 时中止后台操作。”
这是怎么回事?是否线程安全?
最佳答案
因为BackgroundWorker继承自Component,而Component又继承自MarshalByRefObject。 MBRO 对象可能驻留在另一台机器或另一个进程或应用程序域中。这是通过让代理模拟对象来实现的,该代理具有所有完全相同的属性和方法,但其实现通过网络编码调用。
这样做的一个副作用是抖动无法内联方法和属性,这会破坏代理。这也阻止了将字段值存储在 cpu 寄存器中的任何优化。就像 volatile 一样。
关于c# - BackgroundWorker.CancellationPending 线程安全如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6966573/