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. How to combine QtConcurrent with QMetaObject::invokeMethod?
Forum Updated to NodeBB v4.3 + New Features

How to combine QtConcurrent with QMetaObject::invokeMethod?

Scheduled Pinned Locked Moved Unsolved General and Desktop
2 Posts 2 Posters 536 Views 1 Watching
  • 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, 22:43 last edited by
    #1

    Re: How to Use Non Static function in QtConcurrent::run() Method

    Based on a previous post as well as the one referenced above, I have realized that I am trying to get a QFuture from running QtConcurrent::run on a method that accesses a GUI. I am doing this outside of whatever thread the GUI is on.

    // The callback here just sets a boolean so that a button can be enabled. [
    connect(&m_modelsLoadedWatcher, &QFutureWatcher<bool>::finished, this, &ConfigDialog::onNNModelsLoaded);
    m_modelsLoadedFuture = QtConcurrent::run(engine, &wise::Engine::loadPytorchModelsAsync);  
    m_modelsLoadedWatcher.setFuture(m_modelsLoadedFuture);
    

    I read that QMetaObject::invokeMethod "invokes" the method you want from a child class of QObject.

    1. Does invokeMethod somehow cause the method to be called from the thread that is handling the GUI? Is this just to make sure that multiple threads aren't touching the same components?

    2. How does one put this together with QtConcurrent::run?

    I need to get a QFuture<void> back, but passing in invokeMethod returns a bool. I'm unclear then how to mix the two since the return type of the invoked method is void to match my future.

    Should I just change the future's type from void to bool?

    I apologize for the naivety. Here's what I tried:

    I changed the above code to this:

            m_modelsLoadedFuture = QtConcurrent::run(
                // loadModels touches GUI stuff, so have to use invokeMethod
                QMetaObject::invokeMethod(engine, 
                    // wrap in lambda, because you cant use a pointer for bound method 
                    //to do anything but call the method. 
                    [engine]() { 
                        engine->loadPytorchModelsAsync(); 
                    }
                )
            );
    
    

    However, this doesn't seem right to me. Now QtConcurrent is returning a future for the invokeMethod, which doesn't tell me anything about the final status of loadPytorchModelsAsync... For instance m_modelsLoadedFuture.isFinished() would tell me only that the loading started, not that it was finished and returned.

    1 Reply Last reply
    0
    • C Offline
      C Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on 18 Nov 2022, 02:34 last edited by Chris Kawa
      #2

      Does invokeMethod somehow cause the method to be called from the thread that is handling the GUI?

      invokeMethod has a connection type argument. By default it's auto-connection. This means that the method is called on the thread the target object (engine in your code) lives in. If it lives on the GUI thread it's gonna be called on the GUI thread. If it lives on the same thread the invokeMethod was called on it will be called on the same thread, as if by a direct function call. If the method that invokeMethod runs is executed on a different thread then by default it is fire-and-forget type of call i.e. it queues the call on the target thread and returns immediately. If you want to wait for it to finish then you need to tell it to block via the connection type argument.

      I need to get a QFuture<void> back, but passing in invokeMethod returns a bool

      The future should have the same type as the return type of the function you're calling, because it is used to get that return value. So if your loadPytorchModelsAsync returns a bool the future will be of type QFuture<bool> and the same for the watcher QFutureWatcher<bool>. If loadPytorchModelsAsync is void then the future and the watcher should be too.

      How does one put this together with QtConcurrent::run?

      So, although syntactically correct what you wrote makes little sense.
      In your code QtConcurrent::run starts QMetaObject::invokeMethod on another thread. Because you didn't specify otherwise, QMetaObject::invokeMethod uses an auto connection, so adds an event to the engine thread and that calls the lambda. So it's pretty much as if you'd call the invokeMethod directly, without QtConcurrent, just slower because it delegates that to another thread.

      If I understand you correctly you want to run some code asynchronously, get a future watcher for it and then do something when it finishes. That code needs to call something on the GUI thread as part of whatever it is doing.
      If that's what you mean then you'd rather have something like this:

      // This will run the lambda that calls loadPytorchModelsAsync on another thread
      m_modelsLoadedFuture = QtConcurrent::run([=](){ return engine->loadPytorchModelsAsync(); });
      // and then setup the watcher like you did
      

      and your loadPytorchModelsAsync method would look something like this:

      bool wise::Engine::loadPytorchModelsAsync()
      {
         // do some stuff on this thread
      
         // run DoSomethingOnTheHomeThread on the thread this instance lives in (GUI?)
         // and block until it finishes 
         QMetaObject::invokeMethod(this, &wise::Engine::DoSomethingOnTheHomeThread, Qt::BlockingQueuedConnection);
      
         // do some other stuff on this thread
         return something;
      }
      
      1 Reply Last reply
      1

      1/2

      17 Nov 2022, 22:43

      • Login

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