use*_*661 3 c++ qt multithreading signals-slots
假设我有一个sendImage(const QImage&)连接到updateLabel(const QImage&)另一个线程中的插槽的信号,它将QImage转换为QPixmap,然后将其放入QLabel.现在我想知道,如果我使用一个函数const QImage& prepareImage()作为信号的参数,例如emit sendImage(prepareImage()),每秒发出几十次信号,它是线程安全还是有可能在prepareImage和updateLabel之间发生竞争条件图像同时崩溃程序?
值得庆幸的是,Qt可以保护您自己并且会复制图像,这样您就不会在脚下射击.复制将在信号发射时完成,并从信号的实现内部完成 - 这里,复制Object::source在调用堆栈上完成.
鉴于a QImage是隐式共享的,初始副本将是便宜的,但如果主线程然后修改源图像,它将强制进行深层复制.如果您的修改是废弃的源,那么用新的替换源图像而不是"修改"它将更有效.
输出:
data is at 0x7fff5fbffbf8 in main thread QThread(0x10250a700)
0x7fff5fbffbf8 was copied to 0x1025115d0 in thread QThread(0x10250a700)
got 0x1025115d0 in thread QThread(0x7fff5fbffb80)
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
class Copyable {
public:
   Copyable() {}
   Copyable(const Copyable & src) {
      qDebug() << static_cast<const void*>(&src) << "was copied to"
               << static_cast<void*>(this) << "in thread" << QThread::currentThread();
   }
};
Q_DECLARE_METATYPE(Copyable)
class Object : public QObject {
   Q_OBJECT
public:
   Q_SIGNAL void source(const Copyable &);
   Q_SLOT void sink(const Copyable & data) {
      qDebug() << "got" << static_cast<const void*>(&data) << "in thread"
               << QThread::currentThread();
      // Queue a quit since we are racing with app.exec(). qApp->quit() is a no-op before
      // the app.exec() has had a chance to block.
      QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
   }
};
class Thread : public QThread { public: ~Thread() { quit(); wait(); } };
int main(int argc, char *argv[])
{
   QCoreApplication app(argc, argv);
   Copyable data;
   qDebug() << "data is at" << static_cast<void*>(&data) << "in main thread" << app.thread();
   qRegisterMetaType<Copyable>();
   Object o1, o2;
   Thread thread;
   o2.moveToThread(&thread);
   thread.start();
   o2.connect(&o1, &Object::source, &o2, &Object::sink);
   emit o1.source(data);
   return app.exec();
}
#include "main.moc"
| 归档时间: | 
 | 
| 查看次数: | 1292 次 | 
| 最近记录: |