线程似乎停止运行时,我调用一个给定的方法在同一类,为什么
本文关键字:一类 为什么 方法 运行时 线程 调用 一个 | 更新日期: 2023-09-27 18:11:02
我有一个类,不断刷新设备物理连接到PC通过USB。监视方法运行在检查_monitoring
标志的线程上,Start
和Stop
方法只是设置和取消该标志。
我目前的问题是:当线程运行时,我得到预期的"忙"answers"不忙"控制台打印,但是当我调用Stop
方法时,它永远保持运行while(_busy)
,因为不知怎的 _monitoringThread
似乎停止运行!
我怀疑它停止运行是因为最后一次打印总是busy
,也就是说,ExecuteMonitoring
在中途运行,然后没有人知道(至少我不知道)。
暂停调试并查看StackTrace也没有帮助,因为它永远保留在Stop()
方法中的while(_busy)
语句中。
public class DeviceMonitor
{
bool _running;
bool _monitoring;
bool _busy = false;
MonitoringMode _monitoringMode;
Thread _monitoringThread;
readonly object _lockObj = new object();
// CONSTRUTOR
public DeviceMonitor()
{
_monitoringThread = new Thread(new ThreadStart(ExecuteMonitoring));
_monitoringThread.IsBackground = true;
_running = true;
_monitoringThread.Start();
}
public void Start()
{
_monitoring = true;
}
public void Stop()
{
_monitoring = false;
while (_busy)
{
Thread.Sleep(5);
}
}
void ExecuteMonitoring()
{
while (_running)
{
Console.WriteLine("ExecuteMonitoring()");
if (_monitoring)
{
lock (_lockObj)
{
_busy = true;
}
Console.WriteLine("busy");
if (_monitoringMode == MonitoringMode.SearchDevices)
{
SearchDevices();
}
else
if (_monitoringMode == MonitoringMode.MonitorDeviceConnection)
{
MonitorDeviceConnection();
}
lock (_lockObj)
{
_busy = false;
}
Console.WriteLine("not busy");
}
Thread.Sleep(1000);
_busy = false;
}
}
private void SearchDevices()
{
var connected = ListDevices();
if (connected.Count > 0)
{
Device = connected.First();
ToggleMonitoringMode();
}
else
Device = null;
}
void MonitorDeviceConnection()
{
if (Device == null)
{
ToggleMonitoringMode();
}
else
{
bool responding = Device.isConnected;
Console.WriteLine("responding " + responding);
if (!responding)
{
Device = null;
ToggleMonitoringMode();
}
}
}
void ToggleMonitoringMode()
{
if (_monitoringMode == MonitoringMode.SearchDevices)
_monitoringMode = MonitoringMode.MonitorDeviceConnection;
else
if (_monitoringMode == MonitoringMode.MonitorDeviceConnection)
_monitoringMode = MonitoringMode.SearchDevices;
}
enum MonitoringMode
{
SearchDevices,
MonitorDeviceConnection
}
}
最可能的解释是:优化:编译器看到_busy
在Stop
方法中从未更改,因此允许通过用true
替换_busy
将其转换为无限循环。这是有效的,因为_busy
字段没有被标记为易失性,因此优化器不必假设在另一个线程上发生了更改。
因此,尝试将_busy
标记为易失性。或者,甚至更好——实际上要好得多——使用ManualResetEvent
:
ManualResetEvent _stopMonitoring = new ManualResetEvent(false);
ManualResetEvent _monitoringStopped = new ManualResetEvent(false);
ManualResetEvent _stopRunning = new ManualResetEvent(false);
public void Stop()
{
_stopMonitoring.Set();
_monitoringStopped.Wait();
}
void ExecuteMonitoring()
{
while (!_stopRunning.Wait(0))
{
Console.WriteLine("ExecuteMonitoring()");
if(!_stopMonitoring.Wait(0))
{
_monitoringStopped.Unset();
// ...
}
_monitoringStopped.Set();
Thread.Sleep(1000);
}
}
代码来自内存,可能包含一些拼写错误。