Problem In Calling local function with QtConcurrent inside MainWindow



  • Hello My Friends
    I have GUI QT application. i can run QtConcurrent::Run for calling function inside other classes and it works perfectly.
    for example the bellow line works:

    MainWindow.cpp

    WipeBrowsers wb;
    QtConcurrent::run(&this->wb,&WipeBrowsers::wipe,QStringList(MyList));
    

    now i need to insert some QStringList datas to QTreeWidget, and it may take long time and hang my app. so i need a thread. for first try i decide to create a new class and sending MyList and Ui>TreeWidget as parameter. after 1 days and getting many errors, i decide to create myFunction inside MainWindow and just sending QStringList(MyList) as parameter so i have directly access the TreeWidget but every things i do have too many errors.
    In This Document showing a simple example but why my code has to many errors.
    this is my showTree function that i need to call.

    void MainWindow::showTree(QStringList datas)
    {
        for(int i=0;i< datas.size();i++){
              qDebug() << datas[i];  
            }
    }
    

    and i call it with multiple tries like

    QtConcurrent::run(&MainWindow::showTree,QStringList(filename));
    
    QtConcurrent::run(showTree,QStringList(filename));
    
    QtConcurrent::run(&MainWindow::showTree,filename);
    
    QtConcurrent::run(this,&MainWindow::showTree,QStringList(filename));
    

    and .... .

    for example with the bellow code:

    QtConcurrent::run(&MainWindow::showTree,QStringList(filename));
    

    i got many errors like bellow:

    C:\Users\vahid\Documents\qt projects\Emha\mainwindow.cpp:239: error: C2893: Failed to specialize function template 'QtPrivate::QEnableIf<!QtPrivate::HasResultType<T>::Value,QFuture<unknown-type>>::Type QtConcurrent::run(Functor,const Arg1 &)'
    With the following template arguments:
    'Functor=void (__cdecl MainWindow::* )(QStringList)'
    'Arg1=QStringList'
    
    C:\Users\vahid\Documents\qt projects\Emha\mainwindow.cpp:239: error: C2780: 'QtPrivate::QEnableIf<!QtPrivate::HasResultType<T>::Value,QFuture<unknown-type>>::Type QtConcurrent::run(Functor)' : expects 1 arguments - 2 provided
    
    C:\Users\vahid\Documents\qt projects\Emha\mainwindow.cpp:239: error: C2780: 'QFuture<T> QtConcurrent::run(T (__cdecl *)(Param1,Param2,Param3,Param4),const Arg1 &,const Arg2 &,const Arg3 &,const Arg4 &)' : expects 5 arguments - 2 provided
    

    please help. what i must to do.
    thank you very much



  • Hi

    Maybe some help can be found here:
    http://doc.qt.io/qt-5/qtconcurrentrun.html
    (see section Additional API Features - Using Member Functions)

    "QtConcurrent::run() also accepts pointers to member functions. The first argument must be either a const reference or a pointer to an instance of the class. Passing by const reference is useful when calling const member functions; passing by pointer is useful for calling non-const member functions that modify the instance."


  • Moderators

    First of all remember that you can't access any widgets in non-ui thread, so you shouldn't access QTreeWidget in showTree(). Btw. this name becomes very misleading as you can't show anything in a non-ui thread.

    Next, since showTree is a method of MainWindow it needs an instance it can be run on. Thus you need to use a a QtConcurrent::run variant that takes an object pointer and pointer to member function. The last one should work if you run it from a method of MainWindow class, otherwise you need to change this to a valid pointer to your MainWindow instance.



  • Thank you @ttuna
    Maybe you right but my problem not resolved. I'm not pro in QT but based on what you said i try this simple example. but failed.do you know what is my problem?

    const QString hi = "hello";
    QtConcurrent::run(&MainWindow::showTree,QString(hi));
    void MainWindow::showTree(QString datas)
    {
        qDebug() << "just show something please!!!";
    }
    

    it has 8 errors.

    C:\Users\vahid\Documents\qt projects\Emha\mainwindow.cpp:240: error: C2893: Failed to specialize function template 'QtPrivate::QEnableIf<!QtPrivate::HasResultType<T>::Value,QFuture<unknown-type>>::Type QtConcurrent::run(Functor,const Arg1 &)'
    With the following template arguments:
    'Functor=void (__cdecl MainWindow::* )(QString)'
    'Arg1=QString'
    
    C:\Users\vahid\Documents\qt projects\Emha\mainwindow.cpp:240: error: C2780: 'QtPrivate::QEnableIf<!QtPrivate::HasResultType<T>::Value,QFuture<unknown-type>>::Type QtConcurrent::run(Functor)' : expects 1 arguments - 2 provided
    
    C:\Users\vahid\Documents\qt projects\Emha\mainwindow.cpp:240: error: C2780: 'QFuture<T> QtConcurrent::run(T (__cdecl *)(Param1,Param2,Param3,Param4,Param5),const Arg1 &,const Arg2 &,const Arg3 &,const Arg4 &,const Arg5 &)' : expects 6 arguments - 2 provided
    
    C:\Users\vahid\Documents\qt projects\Emha\mainwindow.cpp:240: error: C2780: 'QFuture<T> QtConcurrent::run(T (__cdecl *)(Param1,Param2,Param3,Param4),const Arg1 &,const Arg2 &,const Arg3 &,const Arg4 &)' : expects 5 arguments - 2 provided
    
    C:\Users\vahid\Documents\qt projects\Emha\mainwindow.cpp:240: error: C2780: 'QFuture<T> QtConcurrent::run(T (__cdecl *)(Param1,Param2,Param3),const Arg1 &,const Arg2 &,const Arg3 &)' : expects 4 arguments - 2 provided
    
    C:\Users\vahid\Documents\qt projects\Emha\mainwindow.cpp:240: error: C2780: 'QFuture<T> QtConcurrent::run(T (__cdecl *)(Param1,Param2),const Arg1 &,const Arg2 &)' : expects 3 arguments - 2 provided
    
    C:\Users\vahid\Documents\qt projects\Emha\mainwindow.cpp:240: error: C2784: 'QFuture<T> QtConcurrent::run(T (__cdecl *)(Param1),const Arg1 &)' : could not deduce template argument for 'T (__cdecl *)(Param1)' from 'void (__cdecl MainWindow::* )(QString)'
    
    C:\Users\vahid\Documents\qt projects\Emha\mainwindow.cpp:240: error: C2780: 'QFuture<T> QtConcurrent::run(T (__cdecl *)(void))' : expects 1 arguments - 2 provided
    


  • @mjzarrin
    As the doc points out you have to pass a const reference or a pointer to run() - e.g.:

    QtConcurrent::run(&main_window, &MainWindow::showTree, QLatin1String("hi"));
    // replace main_window with your MainWindow object ...
    


  • @ttuna
    Thank you.
    your right. but still have a problem. in the first argument i means "&main_window" , it is an object of MainWindow. if i declare it above QtConcurrent::run like bellow

    MainWindow main_window;
    QtConcurrent::run(&main_window, &MainWindow::showTree,QStringList(filename));
    

    it works and qDebug in showTree() print filenames but the program can't access UI. I Think after calling QtConcurrent::run the new declared main_window could not access UI. for example treeShow() like bellow

    void MainWindow::showTree(QStringList datas)
    {
        QMessageBox::information(this,"hello","you");
    }
    

    get Debug Error as pop up in run time that says:

    Module: 5.5.0
    File: global\qglobal.cpp
    Line: 2978
    ASSERT failure in QWidget: "Widgets must be created in the GUI thread.", file kernel\qwidget.cpp, line1126
    

    my goal was updating treeWidget without hanging my application. i don't know it is possible or not, but your solution is correct if i dont need UI.
    thank you again and again.


  • Qt Champions 2018

    As Chris Kawa already mentioned you should never try to access UI from another thread than the one where the UI is running!


Log in to reply