c# - BackgroundWorker.CancellationPending 线程安全如何?

标签 c# .net multithreading thread-safety backgroundworker

取消 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/

相关文章:

c# - Identity 2.0.0 中的 ApplicationUser 和 ApplicationRole 导航属性

c# - 与 MySql 连接时,C# 中的访问被拒绝错误。我已经拥有数据库的完全访问权限

c# - WPF SignalR 服务器返回 HTTP 400 错误请求(主机地址无效)

.net - VB.Net 序列化和反序列化私有(private)成员 - 简单示例

ios - 在后台线程中将核心数据从一个数据库复制到另一个数据库

c# - 替代 ToString() 进行索引搜索(C# 转换为 SQL)

c# - ASP.NET MVC : Controller or ControllerBase? 中 Controller 的内置基类

c# - nHibernate 更新什么都不做

c# - 如何从工作线程/类更新GUI线程/类?

c# - HostingEnvironment.QueueBackgroundWorkItem - 澄清?