2016-07-14 259 views
3

我在C#中的多線程有點困難。從其他線程停止線程

我只需激活線程:

 getMultiVarEnabled = true; 
     Globals.readThread = new Thread(readMultipleVarForTextBoxes); 
     Globals.readThread.IsBackground = true; 
     Globals.readThread.Start(); 

內螺紋:

 Globals.PIC.recievingMultiple = true; 
     while (getMultiVarEnabled) // dodaj timeout 
     { ... } 
     Globals.PIC.recievingMultiple = false; 
     Globals.readThread.Abort(); 

,並停止從主線程的線程使用:

 if (getMultiVarEnabled) 
     { 
      getMultiVarEnabled = false;  
      while (Globals.PIC.recievingMultiple); 
      Globals.readThread.Join(); 
      Globals.readThread = null; 
     } 

的問題是,有時(並不總是)我的程序停止線:

  while (Globals.PIC.recievingMultiple); 

有誰知道什麼是使該故障發生的?

最好的問候, 克里斯

+1

有趣的代碼格式,我喜歡它:) – ViRuSTriNiTy

+0

Globals.PIC.recievingMultiple'聲明爲volatile嗎?爲什麼要從它裏面中止readThread?只需在'readMultipleVarForTextBoxes'中使用'return'即可。 – JeffRSon

+0

關於代碼的一些評論。在多線程代碼共享中,狀態是錯誤的主要來源。靜力學不是你認爲他們的朋友。你也不需要放棄自己_Inside thread:_'Globals.readThread.Abort();',理想情況下你不用任何地方的'Abort',只要停止執行代碼即退出循環。 –

回答

3

它的失敗很可能是由於競爭狀態。我假設recievingMultiple在線程啓動之前未初始化,所以它默認爲false

所以,當你執行以下操作:

while (Globals.PIC.recievingMultiple); 

...有一個機會,它是false等等while完全跳過。

使用AutoResetEvent; ManualResetEvent或至少Interlocked.CompareExchange; Interlocked.Read比普通變量更安全。

產生一個線程只是爲了立即阻止它完成排序的目的是線程。

4

你真的應該避免Thread.Abort()。如果您給線程的方法退出,線程將自動關閉。因此,在您的線程中,只需刪除中止呼叫並離開該方法即可。如果您需要預先退出該線程並希望通知它,請使用CancellationToken

此外,如果您想創建一些工作項,應該由一次線程處理,而不是提供這些(也是不可變的)工作項的不可變列表(例如數組)。線程本身可以創建工作完成後返回的結果列表。也許你應該看看生產者的消費模式

使用將從不同線程操作的共享狀態總是會導致難以調試的問題。不變性是你的朋友在這裏。

僅作爲示例,Roslyn編譯器內部使用所有不可變對象的方式,並且僅用於消除大多數發生的競爭條件。