【发布时间】:2013-12-27 21:42:03
【问题描述】:
我有一个 QThread 运行一些代码,我希望它能够很好地退出并进行一些清理,所以代码如下:
testdevice.h
class testDevice : public QThread
{
Q_OBJECT
... // some definitions
protected:
void run(void);
private:
hid_device *handle;
bool abort;
public:
~testDevice(void);
};
testdevice.cpp
testDevice::~testDevice(void)
{
mutex.lock();
abort = true;
mutex.unlock();
wait();
if (handle != NULL)
{
hid_close(handle);
}
hid_exit();
}
void testDevice::run(void)
{
while(true)
{
mutex.lock();
if(abort)
{
return;
}
mutex.unlock();
if (_connected)
{
//... more code
}
else // Case device is not connected
{
emit deviceConnected(_connected);// A breakpoint in here is not triggered after abort is true
handle = hid_open(TEST_VID, TEST_PID, NULL); // this is where VS2010 shows the error "Unhandled exception at 0x71241a95 in project.exe: 0xC0000005: Access violation."
//...code continues
我期望的行为是调用run(),当调用~testDevice()析构函数时abort设置为true和wait阻塞析构函数,runreturns然后析构函数继续.
发生的事情是 run() 被调用,当我关闭应用程序时,析构函数 ~testDevice() 被调用,abort 设置为 true 和 wait() 返回并且析构函数完成......但是然后run() 继续运行,我在 project.exe 中的 0x71241a95 处得到未处理的异常:0xC0000005:访问冲突.....我将其作为 VS2010 调试运行,如果我放置断点,我会一直得到这个,但没有断点我只是偶尔得到这个……有什么线索吗?
奇怪的是,当我在abort = true; 中放置一个断点时,有时第一个断点会出现一个蓝色的小“!”标志,第二次击中是普通的全红。 emit deviceConnected(_connected); 的断点也会发生同样的情况,但这也有点随机......我不知道这是什么“!”意味着...所有这些都可能是调试问题吗?
我的普遍怀疑是 HIDAPI 在单独的线程中运行,并且当有人调用 hid_exit(); 时,它有自己的错误,也许 hid_read(); 继续运行并且由于调用了 hid_quit();,hid_read(); 丢失了一些指针并且没有关闭...只是一个狂野的镜头,为了确认这一点,我需要 HIDAPI 的一些开发人员前来并说点什么...我希望他们能阅读这篇文章
【问题讨论】:
-
阅读有关线程安全、同步(和原子)的信息 - 您正在阅读和修改
abort并使用两个没有同步的不同线程 => 未定义的行为。 -
我过去写了一个很好的答案:stackoverflow.com/questions/19388207/how-to-stop-thread-qthread/… 基本上,您使用
volatile bool而不是bool,编译器不会过度优化您的逻辑。或者您可以查看 Qt 附带的一些不错的线程同步功能。希望对您有所帮助。 -
@LaszloPapp:无论是分配一个常量值还是大象都与它无关。数据竞争的定义(在 C++11 和 C11 中)是(简化的)“两个线程访问同一个(非原子)对象,并且其中至少一个执行写入”。这里不能保证在一个线程中写入
abort对另一个线程是可见的,这是未定义的行为。 -
@LaszloPapp:根据我对问题的理解,OP 在关闭应用程序时正在调用一个特定 QThread 的析构函数。该特定析构函数将(可能)从主线程运行,并尝试对运行该特定 QThread 的
run()方法但设置abort的线程产生影响。那是“非法的”。如果没有共享数据,显然不存在线程安全问题。 -
@Mat: 但他在设置中止后等待线程退出。那么同步有什么问题呢? OP似乎已经做到了。请注意,abort 成员数据是特定于线程的,因此不同线程(QThread 实例)之间没有共享。
标签: c++ multithreading qt qthread qtcore