【发布时间】:2012-11-17 05:38:17
【问题描述】:
我有一个线程阻塞,直到从系统资源(如 USB 设备)接收到数据。我之所以选择这个模型,是因为数据量可能会有所不同,并且随时可能收到数据。退出应用程序后,我收到消息“QThread: Destroyed while thread is still running”。我应该如何关闭这些线程?
我查看了其他问题/解决方案,例如:
- http://www.qtcentre.org/threads/14429-Loop-inside-Qthread-causes-quot-QThread-Destroyed-while-thread-is-still-running-quot
- http://www.qtcentre.org/threads/6211-QThread-Destroyed-while-thread-is-still-running
第一个解决方案涉及使用标志(包含在我的代码中),但是我的线程永远不会到达标志检查。 第二个解决方案使用 QWaitCondition,但似乎与第一个解决方案相同。
我已包含以下代码的精简版本。系统调用的 WaitForSingleObject() 是我实际使用的 (GetOverlappedResult()) 的替代品。
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <QObject>
#include <QThread>
#include <QReadWriteLock>
#include <QDebug>
#ifdef Q_OS_WIN
#include <windows.h>
#endif // Q_OS_WIN
#ifdef Q_OS_LINUX
#include <unistd.h>
#endif // Q_OS_LINUX
////////////////////////////////////////////////
//
// Worker Object
//
////////////////////////////////////////////////
class Worker : public QObject {
Q_OBJECT
public:
QReadWriteLock lock;
bool running;
public slots:
void loop() {
qDebug() << "entering the loop";
bool _running;
forever {
lock.lockForRead();
_running = running;
lock.unlock();
if (!_running) return;
qDebug() << "loop iteration";
#ifdef Q_OS_WIN
HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
WaitForSingleObject(event, INFINITE);
#endif // Q_OS_WIN
#ifdef Q_OS_LINUX
read(0, 0, 1);
#endif // Q_OS_LINUX
}
}
};
////////////////////////////////////////////////
//
// Controller
//
////////////////////////////////////////////////
class Controller {
public:
Controller() {
myWorker.connect(&myThread, SIGNAL(started()), &myWorker, SLOT(loop()));
myWorker.moveToThread(&myThread);
myThread.start();
}
~Controller() {
// Safely close threads
myWorker.lock.lockForWrite();
myWorker.running = false;
myWorker.lock.unlock();
myThread.quit();
//myThread.wait();
//myThread.exit();
//myThread.terminate();
}
private:
QThread myThread;
Worker myWorker;
};
#endif // CONTROLLER_H
【问题讨论】:
-
为什么不用Qt自带的IO函数,比如QFile等呢?它们与信号和插槽一起使用,因此您可以只观看
bytesReadyRead信号。 -
@satuon 我正在制作自己的 QIODevice,它可以读写 HID 设备。虽然这在我之前从未发生过,但也许可以使用 QFile 来访问这些设备。我试试看,谢谢。
-
顺便说一句,您可以通过使其更短更简洁来改进您的问题 - 我读了不到 10%,因为它太长了。此外,您应该只发布代码的相关部分,而不是整个文件。
-
@satuon 使用 QFile 不起作用。虽然 QFile::open() 返回 true,但写入和读取不起作用,可能是因为设备是顺序的。我也尝试了QtSerialPort 库,但 SerialPort::open() 返回 false。尽管我已经从原始问题中删减了一些内容,但这个问题的长度并没有错。代码已经被剥离,只包含 2 个类和 3 个函数。
-
好的,然后使用
WaitForMultipleObjects,并添加第二个对象,例如 HEVENT,当线程需要完成时发送。
标签: multithreading qt blocking system-calls