2012-07-17 47 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