QML/C++ multithreading interconnection crash



  • Hi ,
    I have a problem which I'm unable to solve.

    A Worker object which is QObject derived, do some scanning on serial port and lives in thread A. Here I emit signal which is connected to QML GridView, which lives in thread B. This gridview should act like progress bar - show "what" is currently scanned on serial port to user. It's coded like this:

    @
    class Worker: public QObject
    {
    QThread WorkerThread;
    signals:
    void started();
    void progress(int current)
    ...
    public:
    void scan(int from, int to){
    ...
    this->moveToThread(WorkerThread);
    connect(this, SIGNAL(started()), this, SLOT(run()), Qt::QueuedConnection);
    WorkerThread->start();
    while(!WorkerThread->isRunning());
    emit started();
    ...
    }

     void run(){
         ...
         do{
             emit progress(current);
             ...//do some job
             current++;
         } while( current != to);
     }
    

    }
    @
    QML:
    @
    Item{
    property int currentAddress: -1
    GridView {
    model: ListModel { id: addressModel}
    currentIndex: currentAddress
    highlight: ...
    }

    MouseArea{
    onClicked: startScan(0,250)
    }

    function startScan(from, to){
    addressModel.clear()
    for(var i = from; i <= to; i++){
    addressModel.append({address: i})
    }
    currentAddress = from
    scanner.find(from, to)
    }
    }
    @
    Main:
    @
    ...
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("scanner", new Worker())
    ...
    @

    It works fine for first n addresses, but then the program crashes with following debug output:

    ASSERT: "engine->jsStackTop >= mark" in file ....\include\QtQml\5.2.0\QtQml/private/../../../../../src/qml/jsruntime/qv4scopedvalue_p.h, line 74
    Invalid parameter passed to C runtime function.
    Invalid parameter passed to C runtime function.

    and after that is printed only
    QML GridView: Binding loop detected for property "currentIndex"

    Funny thing is that it works for small range of adresses. It seems like some main thread stack overflow, maybe it can't handle big sizes of signal queue? When I put sleep, say for a second, after signal emit, than it works without problem, so could this be the reason or am I missing something?

    Thank you for your help



  • If your Worker object is created in the main GUI thread, the even loop of main GUI thread is blocked because of "while(!WorkerThread->isRunning());".

    You should not block main GUI thread.

    Possibly, you are using QThread wrongly.



  • Hello and welcome to qt-project.org,

    by using while(!WorkerThread->isRunning()); you want to wait until the thread has startet, but i wouldn't recommend to do that because it will freeze your gui-thread if your thread didn't manage to start. Just emit a signal from your thread on start and connect it to your signal started();.

    bq. QML GridView: Binding loop detected for property “currentIndex”

    I am basically ignoring this messages if everything in the QML is working as expected.



  • Hi, thanks for your suggestions.
    I agree that while(!WorkerThread->isRunning()); may be bad construct, but it doesn't solve the problem. Although GUI thread may freeze for awhile, it still continues and both threads are running.
    The run() executive is in different thread than gui, and the problem still persists.

    Ignoring "binding loop" message doesn't help either, when the gui thread still crashes - I guess only QQmlApplicationEngine has some poblem as outlined by this assert
    ASSERT: “engine->jsStackTop >= mark”


Log in to reply
 

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