QThread奇怪的行为

时间:2013-12-27 21:42:03

标签: c++ multithreading qt qthread qtcore

我有一个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设置为truewait阻止析构函数,并且run返回,然后析构函数继续。

正在发生的事情是run()被调用,当我关闭应用程序时,调用析构函数~testDevice()并将abort设置为truewait()返回并且析构函数完成...然后run()继续运行,我在project.exe中的0x71241a95处得到未处理的异常:0xC0000005:访问冲突.....我运行这个作为VS2010调试,如果我放置断点我总是得到这个,但没有断点,我偶尔会得到这个...任何线索?

奇怪的是,当我在abort = true;中放置一个断点时,有时会遇到第一个断点,那里有一个小的蓝色'!'标志,它第二次击中是一个常规的全红色。对于emit deviceConnected(_connected);处的断点也是如此,但这也是随机的......我不知道这是什么'!'意味着...所有这些都可能是调试问题吗?

我一般怀疑HIDAPI是在一个单独的线程中运行的,当有人调用hid_exit(); hid_read();可能hid_quit();继续运行且调用hid_read();时,它有自己的错误,{{ 1}}失去了一些指针并且没有关闭...只是一个疯狂的镜头,为了证实这一点,我需要HIDAPI的一些开发人员前来找一些东西...我希望他们读到这个

1 个答案:

答案 0 :(得分:1)

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

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

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

至于快速解决你遇到的问题,如果手头的问题是布尔值的编译器优化,比如将它放入缓存,你可以尝试使用std::atomic(C +)使其成为原子+11)或QAtomicInt选项。这将确保编译器无法优化读写操作。

您可以使用std typedef编写类似的内容:

std::atomic_bool abort;

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

QAtomicInt abort;