Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Running QtConcurrent on member function resulting in error
QtWS25 Last Chance

Running QtConcurrent on member function resulting in error

Scheduled Pinned Locked Moved Solved General and Desktop
qtconcurrent
8 Posts 2 Posters 700 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    wcneill
    wrote on 17 Nov 2022, 19:24 last edited by wcneill
    #1

    Re: Creating a new thread with QtConcurrent did not work

    I'll caveat this question with this: I am new to C++ (interpret pointers boggle my mind)

    I am following the documentation for QtConcurrent::run here: https://doc.qt.io/qt-6/qtconcurrentrun.html#additional-api-features

    I am attempting to run the following code:

        // This is a pointer to an Engine object from third party library LUI. 
        auto engine = lui::QueryInterop<wise::Engine>(lui::GetLUI());
        if (engine) {
    
            connect(&m_modelsLoadedWatcher, &QFutureWatcher<bool>::finished, this, &ConfigDialog::onNNModelsLoaded);
    
            // Begin loading models in new thread. 
            m_modelsLoadedFuture = QtConcurrent::run(&wise::Engine::loadPytorchModelsAsync, engine);
            m_modelsLoadedWatcher.setFuture(m_modelsLoadedFuture);
    
     
        } else {
           // do some stuff.
        }
    

    However, I am consistently getting the following error.
    ec23d1b9-1a70-4618-81b9-d0042c217d5c-image.png

    I figure something in the called member function must not be compatible. This is what it looks like:

    void Engine::loadPytorchModelsAsync() { 
        QString scriptModulesPath = QDir("plugins:").absolutePath() + QString("/wisePlugin/PyTorchModels/");
    
        // spread out the processing of our heavy NN model loads over multiple threads
        auto pytorchLoadFunctions = wise::nn::GetPyTorchModelLoaders(scriptModulesPath);
        auto numberOfModelsToLoad = pytorchLoadFunctions.size();
        auto progress = new QProgressDialog("Loading Neural Network Models...", "", 0, (int)pytorchLoadFunctions.size(),
                                            lui::GetLUI()->getUI()->mainWindow()->centralWidget());
    
        progress->setCancelButton(nullptr);
        progress->setMinimumDuration(0);
        progress->setValue(0);
    
        // Define lambda function which will update progress bar when a model is loaded.
        wise::IEngine::SubTaskCompleteFunction actionOnComplete = [progress, numberOfModelsToLoad](int numComplete) {
            // invoke on the main thread
            QMetaObject::invokeMethod(qApp, [progress, numComplete] {
                progress->raise(); // bring the widget to the front of the app
                progress->setValue(numComplete);
            });
        };
    
        // Queue load functions
        QueueSimpleBlockingTaskGroup(pytorchLoadFunctions, wise::IEngine::eTaskBlockType::BlockAWorkerThread, actionOnComplete);
    }
    

    I'm not sure where to go from here honestly. It seems that I am following the documentation perfectly but I know that can't be true or this would be working. Can someone show me what I need to correct?

    1 Reply Last reply
    0
    • S SGaist
      17 Nov 2022, 20:51

      The correct way is to not do GUI access in a method called through QtConcurrent::run.

      Emit a signal or use invokeMethod but no direct access.

      W Offline
      W Offline
      wcneill
      wrote on 17 Nov 2022, 23:30 last edited by wcneill
      #8

      @SGaist

      I got it to work by making the QFuture member variable of the class that was handling the GUI stuff, then just accessing it from the class I was working on above.

      if (engine) {
      
              // Engine has a QFuture<void> member for the models being loaded. We will watch it here. 
              connect(&m_modelsLoadedWatcher, &QFutureWatcher<bool>::finished, this, &ConfigDialog::onNNModelsLoaded);
      
              // We know that the implementation of IEngine is Engine, so cast. 
              m_modelsLoadedWatcher.setFuture(dynamic_cast<wise::Engine*>(engine)->m_modelsLoadedFuture);
      
          }
      

      Im curious however about the invokeMethod you were talking about. I started a new thread asking about it, as I did try it out: https://forum.qt.io/topic/140834/how-to-combine-qtconcurrent-with-qmetaobject-invokemethod.

      1 Reply Last reply
      0
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 17 Nov 2022, 19:48 last edited by
        #2

        Hi and welcome to devnet,

        To rule out the obvious, can you build the example successfully ?

        On a side note: you code snippet does not match the error you show in the image.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        W 1 Reply Last reply 17 Nov 2022, 20:29
        1
        • W Offline
          W Offline
          wcneill
          wrote on 17 Nov 2022, 20:06 last edited by
          #3
          This post is deleted!
          1 Reply Last reply
          0
          • S SGaist
            17 Nov 2022, 19:48

            Hi and welcome to devnet,

            To rule out the obvious, can you build the example successfully ?

            On a side note: you code snippet does not match the error you show in the image.

            W Offline
            W Offline
            wcneill
            wrote on 17 Nov 2022, 20:29 last edited by wcneill
            #4

            @SGaist As it turns out, I was looking at the docs for the wrong version. The arguments just needed to be flipped. Thanks for pointing out the difference.

            1 Reply Last reply
            0
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 17 Nov 2022, 20:31 last edited by
              #5

              Now that you mention it, I remember that I thought that there would some trouble with that. Nice catch !

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • W Offline
                W Offline
                wcneill
                wrote on 17 Nov 2022, 20:47 last edited by wcneill
                #6

                @SGaist said in Running QtConcurrent on member function resulting in error:

                Now that you mention it, I remember that I thought that there would some trouble with that. Nice catch !

                Hah, a co-worker taught me how to use intellisense to filter out the 96 overrides of QtConcurrent::run to discover the error :D

                I'm running into new problems now (widgets must be created in GUI thread)... I found this thread which you participated in here, and take its contents to imply that I am calling QtConcurrent::run from a thread that is not the GUI thread, so any widgets created by that call will make this error occur.

                Unfortunately, I'm not sure which thread is the GUI thread, so I guess I just have to move the run call around into different cpp files until I find the right one?

                I feel out of my depth here. I normally write models in Python and someone else does all this C++ work for me. This is what I get for volunteering to learn something new :D

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on 17 Nov 2022, 20:51 last edited by
                  #7

                  The correct way is to not do GUI access in a method called through QtConcurrent::run.

                  Emit a signal or use invokeMethod but no direct access.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  W 1 Reply Last reply 17 Nov 2022, 23:30
                  1
                  • S SGaist
                    17 Nov 2022, 20:51

                    The correct way is to not do GUI access in a method called through QtConcurrent::run.

                    Emit a signal or use invokeMethod but no direct access.

                    W Offline
                    W Offline
                    wcneill
                    wrote on 17 Nov 2022, 23:30 last edited by wcneill
                    #8

                    @SGaist

                    I got it to work by making the QFuture member variable of the class that was handling the GUI stuff, then just accessing it from the class I was working on above.

                    if (engine) {
                    
                            // Engine has a QFuture<void> member for the models being loaded. We will watch it here. 
                            connect(&m_modelsLoadedWatcher, &QFutureWatcher<bool>::finished, this, &ConfigDialog::onNNModelsLoaded);
                    
                            // We know that the implementation of IEngine is Engine, so cast. 
                            m_modelsLoadedWatcher.setFuture(dynamic_cast<wise::Engine*>(engine)->m_modelsLoadedFuture);
                    
                        }
                    

                    Im curious however about the invokeMethod you were talking about. I started a new thread asking about it, as I did try it out: https://forum.qt.io/topic/140834/how-to-combine-qtconcurrent-with-qmetaobject-invokemethod.

                    1 Reply Last reply
                    0

                    6/8

                    17 Nov 2022, 20:47

                    • Login

                    • Login or register to search.
                    6 out of 8
                    • First post
                      6/8
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved