2012-07-17 112 views
4

我可以安全地在两个线程之间共享此“状态”对象吗?线程和UI之间的共享变量C#

private bool status = false; 

    private void uiNewThread_bootloaderStartIdSetupAuto() 
    { 
     while (status) 
      ; 
    } 

以上是新线程将从UI推出如下:

private void uiBtnBootloaderStartIdSetupAuto_Click(object sender, EventArgs e) 
    { 
     if (MessageBox.Show("ID will be setup starting from 1 to 16. \n\nAfter pressing 'YES', press the orange button one-by-one on the nodes.\nThe first pressed node will have number 1, the next number 2, and so on... \n\nWhen done, hit DONE button.", "ID setup", MessageBoxButtons.YesNo) == DialogResult.Yes) 
     { 
      status = true; 
      Thread transmitConfig = new Thread(new ThreadStart(uiNewThread_bootloaderStartIdSetupAuto)); //close port in new thread to avoid 
      transmitConfig.Start(); 
     } 
     else 
     { 
      Log(LogMsgType.Normal, "User cancelled"); 
      status = false;    
     } 
    } 

回答

4

优化,比如缓存或由编译器或CPU可能会破坏你的代码进行重新排序。你应该申报现场volatile防止这种情况:

private volatile bool status = false; 

什么可能出问题的一个例子是,如果两个线程都在不同内核上运行的status值可以在CPU寄存器中的核心缓存轮询线程正在运行,因此永远不会看到其他线程更新的值。

尝试在发布模式下构建您的应用程序,您应该看到这种效果。

+0

在大多数CPU架构和.NET Framework,挥发性或多或少是多余的。乔达菲在这里讨论。 http://www.bluebytesoftware.com/blog/2010/12/04/SayonaraVolatile.aspx – stevethethread 2012-07-17 09:53:04

+0

@stevethethread:在我的系统中,我无数次地重新创建了这个场景,并在.NET中获得了一个死锁。这里的问题是非常真实的。 – Tudor 2012-07-17 09:55:39

+0

不幸的是,即使通常通过使用'volatile'来正常工作,一个'volatile write'也不能保证在宇宙热死之前完成写操作:-) – xanatos 2012-07-17 10:05:59

0

只需锁定变量即可。

private static readonly object _lock = new Object(); 

.... 

lock(_lock){ 
//access to boolean variable etc. 
} 

另一种可能性是将bool包装在Lazy中,并且访问内部值是线程安全的。

如果您想使用无锁定机制来读取和更新该值,则可以考虑使用Interlocked类中的方法。

资讯:

System.Threading.Interlocked