简体   繁体   中英

Qt slot argument is corrupted

The original code is to big to be posted here. Basically, I'm doing this:

class MySuperClass 
{
    QThread thread;
    MyClass myObject;

    MySuperClass() 
    {

        connect( this, &MySuperClass::onKill, &myObject, &MyClass::stop );

        connect( &thread, &QThread::started, &myObject, &MyClass::loop );
        connect(&myObject, &MyClass::finished, &thread, &QThread::quit );

        myObject.moveToThread( &thread );

        qRegisterMetaType<uint16_t>("uint32_t");

        connect( this, &MySuperClass::changed, &myObject, &MyClass::onChange );
    }

    void do()
    {
        emit changed(0);
    }
}

'onKill - stop' signal/slot have no parameters and work fine. No problem here.

Problem is 'changed - onChange' pair. They have one parameter of type uint32_t (which I have registered).

When I call method do of MySuperClass from the main thread the signal is emitted, the slot onChange is called but it's parameter is not 0! It's some big number like 3043426304.

The funny part is: if I change connection type to DirectConnection - parameter is zero; if I change connection type to QueuedConnection - parameter is zero too! How can this be? Isn't AutoConnection either Queued or Direct?

I'm very puzzled by this. First of all: how stack allocated integer type parameter may be corrupted like that? I'd understand if it was something heap-allocated or used in multiple threads.

My second question is: how should I do this connection properly? Does the order of connect and moveToThread matter?

Question 1 is answered by Chris. For question 2 (I did not see that the first time around)...

This is how to setup an object running in a seperate thread:

// Create the myObject object in its own thread
QThread* myThread= new QThread(); // you can assign `this` as parent if you want...
MyObject* myObject= new MyObject(0); // Assign no parent here (for QObject)
QObject::connect(myThread, &QThread::started, myObject, &MyObject::run, Qt::QueuedConnection);
myObject->moveToThread(myThread);
myThread->start();

You mostly have it correct. I think you are missing the "myThread->start()" function to kick the thread off. In your object creation its important to know that any dynamic allocations will be created in the parent thread space since the constructor runs before you move it to the thread. So its best to instantiate any objects you need inside the run() slot.

Any interaction with object once you start the thread should be via slots/signals.

Once you start the thread, it will emit started and your run() slot will be called.

The order of connect and moveToThread does not matter so long as you do all this before you call myThread->start()

Note

This is good for starting up a thread. There are some rules that may help you terminating the thread cleanly as well... but that's probably going off-topic

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM