我的线程(_updater)由此启动:
public void StartCollection()
{
running = true;
_updater = new Thread(new ThreadStart(ContinuousCollect));
_updater.Start();
}
然后它从传感器抓取数据并将其发送到需要的地方。
private void ContinuousCollect()
{
while (running) //Static Boolean that controls whether or not to keep running.
{
lock (_data)
ReadData(ref _data);
//Stuff that doesn't matter
}
}
然后通过这种方法停止:
public void StopCollection()
{
if (_updater != null)
{
if (_updater.ThreadState == ThreadState.Running)
{
running = false;
_updater.Join();
}
_updater = null;
}
}
当我正常运行而没有断点时,它会在尝试读取数据时抛出错误但我已经关闭了COM端口 - 它不应该像我一样关闭试图结束线程。当我在StopCollection()中使用断点并逐步执行时,它正确地将运行更改为false并且_updater研磨为停止,从而导致没有错误。没有断点,_updater即使在我调用StopCollection()之后仍继续运行,并且运行仍然设置为true,即使我将其设置为true的代码中的唯一位置在StartCollection()中。我尝试使用Thread.Abort,但这也没有用。我该怎么办?
答案 0 :(得分:2)
您没有同步访问线程之间共享的内存,这是问题的根源。每个线程都能够缓存特定内存状态的值,只要你没有通过使用内存屏障明确禁止它这样做,所以你的工作线程永远不会检查内存中的实际位置来查看你已经更新了变量。
虽然您可以以某种方式显式同步对变量的访问以确保从多个线程正确访问它,但更惯用的解决方案是使用CancellationToken
,因为它的实现将确保正确同步共享状态,防止令牌被取消的状态被缓存在其他线程中。
调试时会删除所有类型的优化,以及其他以改变未定义行为结果的方式修改的行为,这就是使用调试器时程序行为不同的原因。线程相关的错误通常很难/不可能使用调试器本质上重现,因为观察行为本身的行为会改变行为本身,这就是为什么在多线程环境中进行编程时需要更加小心的原因。使用共享内存。
答案 1 :(得分:0)
尝试制作"跑步"一个动荡的领域。另外请考虑使用Tasks和CancellationTokens作为@Darek建议
答案 2 :(得分:0)
我"修复"问题但可能在此过程中造成了另一个问题。当它检查线程的状态时,线程大多数时间都在WaitSleepJoin
,导致if (_updater.ThreadState == ThreadState.Running)
响应为false,因此永远不会禁用该线程。现在它会检查它是Running
还是WaitSleepJoin
,如果它是,它会改变Running
的状态并且整个事情正确关闭。谢谢大家的帮助!