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 701 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.
  • wcneillW Offline
    wcneillW Offline
    wcneill
    wrote on 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
    • SGaistS SGaist

      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.

      wcneillW Offline
      wcneillW Offline
      wcneill
      wrote on 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
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on 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

        wcneillW 1 Reply Last reply
        1
        • wcneillW Offline
          wcneillW Offline
          wcneill
          wrote on last edited by
          #3
          This post is deleted!
          1 Reply Last reply
          0
          • SGaistS SGaist

            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.

            wcneillW Offline
            wcneillW Offline
            wcneill
            wrote on 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
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on 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
              • wcneillW Offline
                wcneillW Offline
                wcneill
                wrote on 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
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on 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

                  wcneillW 1 Reply Last reply
                  1
                  • SGaistS SGaist

                    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.

                    wcneillW Offline
                    wcneillW Offline
                    wcneill
                    wrote on 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

                    • Login

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