2016-07-14 283 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编译器内部使用所有不可变对象的方式,并且仅用于消除大多数发生的竞争条件。