我有一个读取数据的线程
class MyThread: QThread
{
...
}
void MyThread::run ()
{
uint8_t* buffer; // in my real code, it's a ring, so there is not read during write
// ...
while (true)
{
if (isInterruptionRequested())
return;
USB_READ(buffer);
emit newData(buffer);
}
}
在我的UI类中,我有:
connect(this, &UIClass::newData, m_thread, &MyThread::newData);
// ...
void newData(uint8_t* data)
{
// Process data
}
void UIClass::closeEvent(QCloseEvent *event)
{
disconnect(this, &UIClass::newData, m_thread, &MyThread::newData);
m_thread->requestInterruption();
m_thread->wait();
}
问题是,当我点击“关闭”时,线程被销毁导致指针data
无效。有时调用信号newData
会导致我的函数使用无效指针和段错误。如何确定不会发生?
现在,我使用一个带有任意延迟的std :: this_thread :: sleep_for(),它可以工作,但我觉得这不是很漂亮
我心中想到:
- 断开信号
- 等待执行挂起信号
- 退出
答案 0 :(得分:2)
问题是你从一个线程发送指针到另一个线程而不确保指针保持有效。
您有多种选择来解决这个问题。要么使用QSharedPointer(或来自stl的类似实用程序)来保存数据,这样做会确保指针保持有效(或者如果你也使用QWeakPointer,则提供一种方法来检测指针何时变为无效)。或者您可以使用QByteArray传递数据,但这将复制。
示例1
void MyThread::run ()
{
QSharedPointer<uint8_t> buffer (new uint8_t[N]()); // Do not delete[], QSharedPointer will handle it
...
emit newData(buffer);
}
void newData(QSharedPointer<uint8_t> data)
{
// data is always valid
// Process data
}
示例2
void MyThread::run ()
{
QSharedPointer<uint8_t> buffer (new uint8_t[N]());
...
emit newData(buffer);
}
void newData(QWeakPointer<uint8_t> data)
{
// data might not be valid but we can check
QSharedPointer<uint8_t> buffer (data);
if (!buffer)
return;
// Process data
}
示例3
void MyThread::run ()
{
uint8_t[N] buffer;
...
emit newData(QByteArray(buffer, size));
}
void newData(QByteArray data)
{
// data is valid
// Process data
}
答案 1 :(得分:0)
您需要做的就是让线程比用户界面更长久。这很容易:
class MyThread : public QThread
{
Q_OBJECT
RingBuffer buffer;
public:
void run() override;
~MyThread() {
requestInterruption();
quit();
wait();
}
Q_SIGNAL newData(RingBuffer *);
};
int main(int argc, char **argv) {
QApplication app{argc, argv};
MyThread thread;
thread.start();
UIClass ui;
connect(&thread, &MyThread::newData, &ui, &UIClass::newData);
return app.exec();
}