BackgroundWorker.CancellationPending线程安全如何?取消BackgroundWorker操作的方法是调用BackgroundWorker.CancelAsync()://RUNNINGINUITHREADprivatevoidcancelButton_Click(objectsender,EventArgse){backgroundWorker.CancelAsync();在BackgroundWorker.DoWork事件处理程序中,我们检查BackgroundWorker。CancellationPending://在工作线程中运行voidbackgroundWorker_DoWork(objectsender,DoWorkEventArgse){while(!backgroundWorker.CancellationPending){上面的想法遍布整个网络,包括BackgroundWorker的MSDN页面。现在,我的问题是:这个线程如何安全?我查看了ILSpy中的BackgroundWorker类-CancelAsync()只是在不使用内存屏障的情况下将cancellationPending设置为true,而CancellationPending只是在不使用内存屏障的情况下返回cancellationPending。根据这个JonSkeet页面,上面的内容不是线程安全的。但是BackgroundWorker.CancellationPending的文档说:“此属性旨在供工作线程使用,工作线程应定期检查CancellationPending并在设置为true时中止后台操作。”这里发生了什么?它是线程安全的吗?它是线程安全的。代码while(!backgroundWorker.CancellationPending)正在读取属性,编译器知道它无法缓存结果。因为在普通帧中,每一次Write都等同于一次VolatileWrite,CancelAsync()方法只能设置一个字段。这是因为BackgroundWorker继承自MarshalByRefObject的Component。MBRO对象可以驻留在另一台计算机上,或者驻留在另一个进程或应用程序域中。这是通过让代理模拟一个对象来实现的,该对象具有所有完全相同的属性和方法,但其实现是通过网络编组调用的。副作用之一是抖动无法内联方法和属性,这会破坏代理。这也阻止了在cpu寄存器中存储字段值的任何优化。像挥发性的。一个很好的观点和一个非常公平的怀疑。听起来不像是线程安全的。我想MSDN也有同样的疑问,这就是为什么它存在于BackgroundWorker.CancelAsync方法下。警告请注意,在发出取消请求时,DoWork事件处理程序中的代码可能会完成其工作,并且您的轮询循环可能会将CancellationPending设置为true。在这种情况下,即使发出取消请求,RunWorkerCompleted事件处理程序中System.ComponentModel.RunWorkerCompletedEventArgs的Canceled标志也不会设置为true。这种情况称为竞争条件,是多线程编程中的常见问题。有关多线程设计问题的更多信息,请参阅托管线程最佳实践。我不确定BackgroundWorker类的实现。在这种情况下,了解BackgroundWorker.WorkerSupportsCancellation属性在内部的使用方式很重要。这个问题可以用两种方式解释:1)BackgroundWorker.CancellationPending实现是否正确?这是不正确的,因为它可能会导致取消请求被忽略。该实现使用来自支持字段的普通读取。如果此支持字段由另一个线程更新,则更新可能对读取代码不可见。下面是实现的样子://非易失性变量:privateBooleancancellationPending;publicBooleanCancellationPending{get{//普通读取:returncancellationPending;正确的实现会尝试读取最新的值。这可以通过使用内存屏障或锁来声明支持字段“volatile”来实现。可能还有其他选择,有些比其他更好,但这取决于拥有“BackgroundWorker”类的团队。2)使用BackgroundWorker.CancellationPending的代码是否正确?while(!backgroundWorker.CancellationPending){DoSomething();这段代码是正确的。循环将旋转直到CancellationPending返回“true”。请记住,C#属性只是CLR方法的语法糖。在IL级别,这只是另一个看起来像“get_CancellationPending”的方法。调用代码不会缓存方法返回值(可能是因为判断一个方法是否有副作用太难了)。以上是C#学习教程:BackgroundWorker.CancellationPending线程安全如何实现?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
