C++ 退出前要执行的等待槽
我有一个线程可以读取数据C++ 退出前要执行的等待槽,c++,multithreading,qt,qthread,C++,Multithreading,Qt,Qthread,我有一个线程可以读取数据 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(b
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();
}
问题在于,当我单击“关闭”时,线程被破坏,导致指针数据
无效。有时会调用信号newData
,导致我的函数使用无效指针和segfault。如何确定这不会发生
现在,我使用std::this_thread::sleep_For()并带有任意延迟,它可以工作,但我觉得它不是很漂亮
我脑海中的想法:-断开信号
-等待挂起信号执行
-退出问题在于,您将指针从一个线程发送到另一个线程,但没有确保指针保持有效 你有多种选择来解决这个问题。使用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
}
问题是,您将指针从一个线程发送到另一个线程,而没有确保指针保持有效 你有多种选择来解决这个问题。使用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
}
您所需要做的就是让线程比用户界面更长寿。这相当容易:
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();
}
您所需要做的就是让线程比用户界面更长寿。这相当容易:
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();
}
谢谢你,我试了第一个,它很管用。如果我不想使用动态分配,但想使用address:uint8\u t buffer[size]。。。。。发出缓冲区(&B)[0]。在这种情况下,我能做什么,因为我不希望删除指针(它不能),如果在堆栈上分配缓冲区(而不是在堆上动态分配),则不能保证在调用插槽时它是有效的,因为不能保证缓冲区仍在另一个线程的作用域中。唯一的解决办法是像第三个例子那样复制一份。谢谢你,我肯定需要第一份谢谢,我试了第一份,它正在工作。如果我不想使用动态分配,但想使用address:uint8\u t buffer[size]。。。。。发出缓冲区(&B)[0]。在这种情况下,我能做什么,因为我不希望删除指针(它不能),如果在堆栈上分配缓冲区(而不是在堆上动态分配),则不能保证在调用插槽时它是有效的,因为不能保证缓冲区仍在另一个线程的作用域中。唯一的解决办法是像第三个例子那样复制一份。谢谢你,我肯定需要第一份