当我在同一个类中调用给定方法时,线程似乎停止运行,为什么? [英] Thread seems to stop running when I call a given method in the same class, why?
问题描述
我有一个类,它不断刷新通过 USB 物理连接到 PC 的设备.监控方法在检查 _monitoring
标志的线程上运行,而 Start
和 Stop
方法只是设置和取消设置该标志.
I have a class that constantly refreshes devices physically connected to PC via USB. The monitoring method runs on a thread checking a _monitoring
flag, and Start
and Stop
methods just set and unset that flag.
我当前的问题是:当线程运行时,我得到预期的忙"和不忙"控制台打印,但是当我调用 Stop
方法时,它继续运行 而(_busy)
永远,因为不知何故_monitoringThread
似乎停止运行!
My current problem is: when the thread is running, I get the expected "busy" and "not busy" console prints, but when I call Stop
method, it keeps running while(_busy)
forever, because somehow the _monitoringThread
seems to stop running!
我怀疑它停止运行是因为最后一次打印总是busy
,也就是说,ExecuteMonitoring
在中途运行,然后没人知道(至少我不知道).
I suspect it stops running because the last print is always busy
, that is, the ExecuteMonitoring
runs midway and then nobody knows (at least I don't).
暂停调试并查看 StackTrace 也无济于事,因为它永远保留在 Stop()
方法内的 while(_busy)
语句中.
Pause debugging and looking at StackTrace didn't help either, because it keeps in the while(_busy)
statement inside Stop()
method, forever.
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
中永远不会改变方法,因此允许通过将 _busy
替换为 true
将其转换为无限循环.这是有效的,因为 _busy
字段没有标记为易失性,因此优化器不必假设另一个线程上发生的更改.
The most likely explanation is: optimization: The compiler sees that _busy
is never changed inside the Stop
method and it is therefore allowed to convert this to an endless loop by replacing _busy
with true
. This is valid, because the _busy
field is not marked as being volatile and as such the optimizer doesn't have to assume changes happening on another thread.
因此,尝试将 _busy
标记为 volatile.或者,甚至更好 - 实际上更好 - 使用 ManualResetEvent
:
So, try marking _busy
as volatile. Or, even better - actually A LOT BETTER - use a 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);
}
}
代码来自记忆,可能包含一些拼写错误.
Code is from memory, might contain some typos.
这篇关于当我在同一个类中调用给定方法时,线程似乎停止运行,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!