等待插槽在退出之前执行

我有一个读取数据的线程

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()进行任意延迟,它可以工作,但我不觉得这很漂亮

我在脑海里:
- 断开信号
- 等待信号被执行
- 出口


问题在于你发送一个指针从一个线程到另一个线程而没有确保指针保持有效。

你有多种选择来解决这个问题。 使用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
}

你所需要做的就是让线程超越用户界面。 这很容易:

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();
}
链接地址: http://www.djcxy.com/p/30765.html

上一篇: Waiting slots to be executed before quitting

下一篇: How to pass variadic args to a std::thread?