Signal/Slot between Threads Qt 5



  • Hi People,

    I have a problem with Qt meta-type system and the signal and slot connections.
    I try to connect a signal and slot with each other. The signal looks like this:

    @
    signals: void sigSaveFileName(QString&);
    @

    and the slot:
    @
    private slots: void slotPutSaveFileName(QString& name);
    @

    Before I connect those, I would like register the QString with qRegisterMetaType() method then call connect method:

    @
    qRegisterMetaType<QString>("QString");
    connect(&_worker, &Worker::sigOpenFileName, this, &MainWindow::slotPutOpenFileName);
    @

    If I run my application, I watch the application output, and I get the following warning:
    QObject::connect: Cannot queue arguments of type 'QString&'
    (Make sure 'QString&' is registered using qRegisterMetaType().)
    QObject::connect: Cannot queue arguments of type 'QString&'
    (Make sure 'QString&' is registered using qRegisterMetaType().)

    and doesn't happen anything :(

    Can tell me somebody what I make wrong?

    Regards,
    Norbert


  • Lifetime Qt Champion

    Hi,

    No need to register QString, what you really want to have is

    @
    signals:
    void sigSaveFileName(const QString& name);
    private slots:
    void slotPutSaveFileName(const QString& name);
    @



  • I think the parameter identifier of the signal is not necessary too.


  • Lifetime Qt Champion

    Indeed, it's not, but it's cleaner IMHO



  • If I register or not, I get this warning as output of the application:
    QObject::connect: Cannot queue arguments of type ‘QString&’
    (Make sure ‘QString&’ is registered using qRegisterMetaType().)
    QObject::connect: Cannot queue arguments of type ‘QString&’
    (Make sure ‘QString&’ is registered using qRegisterMetaType().)

    so I think this is the reason because my application doesn't work.

    Regards,
    Norbert

    Update: I would like to use those for communicate between threads: a GUI and a worker thread. By reason of my project is very huge, I made an little test code. In this program I would like communicate between an object which lives in main thread and an other object from the worker thread.
    In this case get I same message, like the mentioned above.

    The header looks like here:

    @
    #include <QThread>
    #include <QString>
    #include <QDebug>

    class myThread: public QThread {

    Q_OBJECT
    

    signals: void sig(QString& contain);
    private: void run() {
    while(true) {
    QString string;
    emit sig(string);
    qDebug() << string;
    QThread::sleep(1);
    }
    }
    };

    class receiver: public QObject {

    Q_OBJECT
    

    public slots: void slot(QString& some){
    some = "from slot";
    }
    };
    @

    and the main method:

    @
    #include <QCoreApplication>

    #include "vmi.h"

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    myThread t;
    receiver r;
    
    QObject::connect(&t, &myThread::sig, &r, &receiver::slot);
    
    t.start();
    
    a.exec&#40;&#41;;
    
    t.wait();
    return 0;
    

    }
    @



  • Try to pass Qt::DirectConnection as a last param (after slot) in QObject::connect. Qt::QueuedConnection connections do not work between threads.


  • Moderators

    [quote author="toptan" date="1368172580"]Try to pass Qt::DirectConnection as a last param (after slot) in QObject::connect. Qt::QueuedConnection connections do not work between threads.[/quote]

    Actually it's the other way around :) QueuedConnection works and stops you from worrying about locking resources, mutexes etc. DirectConnection can cause various threading problems to occur (but it's not prohibited, you just need to be more careful). Quoting from QThread documentation:
    [quote]Note: If you interact with an object, using any technique other than queued signal/slot connections (e.g. direct function calls), then the usual multithreading precautions need to be taken.[/quote]

    Don't use new connect syntax, revert to old one and use QueuedConnection, it should work.


  • Lifetime Qt Champion

    There is something that's bothering me with your design. The idea behind signal and slots is that you send a value with a signal to a slot.

    With
    @public slots:
    void slot(QString& some){
    some = "from slot";
    }@

    you try to emit a signal and have the slot assign the value to the variable and read it after ? Furthermore in a threaded setup ?

    That seems very "unusual"


  • Moderators

    It's not only "unusual". It begs for an ugly crash at some point. Signal is passing a reference to a local variable string. If the queued slot happens to (and most likely will in this setup) fire after string is destroyed it goes into the horrible things land.
    It may work at first look because the compiler is probably optimizing it by placing the string variable in the same place in memory but it's a bug by design.
    This would be ok(well, sorta, it's still ugly) with a direct connection since they're pretty much a function call, but queued connections don't "block" at emitting signals.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.