c++ - QThread 奇怪的行为

标签 c++ multithreading qt qthread qtcore

<分区>

我有一个 QThread 正在运行一些代码,我希望它能够很好地退出并进行一些清理,因此代码如下:

测试设备.h

class testDevice : public QThread 
{
    Q_OBJECT
... // some definitions 

protected:
    void run(void);

private:
    hid_device *handle;
    bool abort;

public:
    ~testDevice(void);
};

测试设备.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 被设置为 truewait 阻塞析构函数,run 返回然后析构函数继续。

发生的事情是 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 站出来说点什么……我希望他们能读到这篇文章

最佳答案

您似乎以自定义方式使用 QThread 而不是通常的 start()quit() 执行。最好的情况是,在一个理想的世界中,如果您可以使用 quit() 来重构您的代码以退出 QThread,因为这将更接近于此的信号/插槽机制QObject 子类。

但是,我同意这并不总是可能的。根据您提供的几行内容,我还不能告诉您在这种特殊情况下它是有意义的,但至少我会鼓励您考虑一下。

此外,您可以使用 QWaitCondition 来等待某事发生,而不是低级别或/和自定义 wait() 调用。

至于快速解决您面临的问题,如果手头的问题是 bool 值的编译器优化(例如将其放入缓存),您可以尝试使用 std::atomic 使其成为原子的(C++11) 或 QAtomicInt选项。这将确保编译器无法优化读取和写入。

你可以用 std typedef 写这样的东西:

std::atomic_bool abort;

如果您需要支持 C++-11 之前的编译器以及 Qt 4,您可以像这样使用 Qt 类:

QAtomicInt abort;

关于c++ - QThread 奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20808217/

相关文章:

qt - Qt中的父代是做什么用的?

c# - 如何锁定具有相同ID的对象?

android - Kotlin Coroutines - 返回流的暂停函数永远运行

c++ - 参数化查询中的参数计数不匹配

c++ - Qt 连接功能 - 使用 lambda 进行信号消歧

java - 据说 `libX11`不是线程安全的。这是否意味着我不能将 Java AWT 与其他也使用 X11 的东西(例如 Qt)混合使用?

qt - Qbs 构建规则如何使用产品

c++ - 为什么这段使用 `::boost::bind` 的代码会出现编译错误?

c++ - 为什么 GCC 在这里优化分配?

c++ - 对参数包中的每个元素应用函数