我在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);
有人知道是什么导致这种错误发生吗?
祝你好运, 克里斯
答案 0 :(得分:4)
你应该真的避免Thread.Abort()
。如果给出一个线程的方法退出,线程将自动关闭。所以在你的线程中只需删除中止调用并离开方法。如果您需要预先退出该主题并希望通知它,请使用CancellationToken
。
此外,如果您想创建一些工作项,那应该由一个线程中的一个线程处理,而不是提供这些(也是不可变的)工作项的不可变列表(例如数组)。然后,线程本身可以创建在工作完成后返回的结果列表。也许你应该看看生产者消费者模式。
使用将从不同线程操纵的共享状态总是导致难以调试的问题。不变性是你的朋友。
仅举例来说,Roslyn编译器内部使用所有不可变对象,immutable collections只是为了消除大多数出现的竞争条件。
答案 1 :(得分:3)
由于竞争条件,它很可能失败。我假设recievingMultiple
在线程启动之前未初始化,因此默认为false
。
所以当你执行以下操作时:
while (Globals.PIC.recievingMultiple);
...有可能是false
,因此完全跳过while
。
使用AutoResetEvent
; ManualResetEvent
或至少Interlocked.CompareExchange
; Interlocked.Read
比纯变量更安全。
产生一个线程只是为了立即阻止它完成某种程度的失败线程的目的。