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. invokeMethod in other thread
Qt 6.11 is out! See what's new in the release blog

invokeMethod in other thread

Scheduled Pinned Locked Moved Unsolved General and Desktop
22 Posts 5 Posters 24.7k Views 2 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.
  • VRoninV Offline
    VRoninV Offline
    VRonin
    wrote on last edited by
    #11

    invokemethod with direct connection is basically the same as a direct call to the method so I'd investigate why it generates a crash

    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
    ~Napoleon Bonaparte

    On a crusade to banish setIndexWidget() from the holy land of Qt

    1 Reply Last reply
    1
    • McLionM Offline
      McLionM Offline
      McLion
      wrote on last edited by
      #12

      The invokeMethod now calls it the same as the direct call - To be honest, I have no clue why the call works today - maybe the full rebuild did the trick ... and overnight ... ;-)
      However, it still crashes.
      Isn't calling this in a different thread the issue? Or I have some other issue - some code segments follow. I'm creating everything in the constructor of the mainwindow:

      // start a new thread and put the LoLaWorker to it
        bLoLaIsInitiated = false;
        QThread* lolathread = new QThread;
        LoLaWorker* lolaworker = new LoLaWorker();
        lolaworker->moveToThread(lolathread);
        connect(lolathread, SIGNAL(started()), lolaworker, SLOT(InitLoLaThread()));
        lolathread->start();
      ... some more connects here
      

      I have #include "LoLaWorkerThread.h" and LoLaWorker *lolaworker; public in header of mainwindow and I am calling

      QMetaObject::invokeMethod(lolaworker, "InitLoLaUDPsocket", Qt::DirectConnection, 
                                Q_ARG(QString, ip4addr),
                                Q_ARG(quint16, port),
                                Q_ARG(QString, location),
                                Q_ARG(QString, name),
                                Q_ARG(QString, MAC),
                                Q_ARG(QString, loglevel));
      

      When emitting the signal everything works - just not immediate, which is what I need.

      I suspect I'm doing something wrong. Any ideas?
      Thanks
      McL

      kshegunovK 1 Reply Last reply
      0
      • McLionM McLion

        The invokeMethod now calls it the same as the direct call - To be honest, I have no clue why the call works today - maybe the full rebuild did the trick ... and overnight ... ;-)
        However, it still crashes.
        Isn't calling this in a different thread the issue? Or I have some other issue - some code segments follow. I'm creating everything in the constructor of the mainwindow:

        // start a new thread and put the LoLaWorker to it
          bLoLaIsInitiated = false;
          QThread* lolathread = new QThread;
          LoLaWorker* lolaworker = new LoLaWorker();
          lolaworker->moveToThread(lolathread);
          connect(lolathread, SIGNAL(started()), lolaworker, SLOT(InitLoLaThread()));
          lolathread->start();
        ... some more connects here
        

        I have #include "LoLaWorkerThread.h" and LoLaWorker *lolaworker; public in header of mainwindow and I am calling

        QMetaObject::invokeMethod(lolaworker, "InitLoLaUDPsocket", Qt::DirectConnection, 
                                  Q_ARG(QString, ip4addr),
                                  Q_ARG(quint16, port),
                                  Q_ARG(QString, location),
                                  Q_ARG(QString, name),
                                  Q_ARG(QString, MAC),
                                  Q_ARG(QString, loglevel));
        

        When emitting the signal everything works - just not immediate, which is what I need.

        I suspect I'm doing something wrong. Any ideas?
        Thanks
        McL

        kshegunovK Offline
        kshegunovK Offline
        kshegunov
        Moderators
        wrote on last edited by
        #13

        @McLion said in invokeMethod in other thread:

        QMetaObject::invokeMethod(lolaworker, "InitLoLaUDPsocket", Qt::DirectConnection, ...
        

        This is a race condition if you're calling this from a thread different than lolathread .

        If you want something to be called first in a thread post the event to the object immediately after moving it to the thread (i.e. it becomes the first event) and don't use direct connection across threads if you don't provide manual access serialization.

            // ...
            lolaworker->moveToThread(lolathread);
            // What's wrong with this?
            QMetaObject::invokeMethod(lolaworker, "InitLoLaUDPsocket", Qt::QueuedConnection, ... );
            // And ... start the event processing
            lolathread->start();
        

        Read and abide by the Qt Code of Conduct

        McLionM 1 Reply Last reply
        2
        • kshegunovK kshegunov

          @McLion said in invokeMethod in other thread:

          QMetaObject::invokeMethod(lolaworker, "InitLoLaUDPsocket", Qt::DirectConnection, ...
          

          This is a race condition if you're calling this from a thread different than lolathread .

          If you want something to be called first in a thread post the event to the object immediately after moving it to the thread (i.e. it becomes the first event) and don't use direct connection across threads if you don't provide manual access serialization.

              // ...
              lolaworker->moveToThread(lolathread);
              // What's wrong with this?
              QMetaObject::invokeMethod(lolaworker, "InitLoLaUDPsocket", Qt::QueuedConnection, ... );
              // And ... start the event processing
              lolathread->start();
          
          McLionM Offline
          McLionM Offline
          McLion
          wrote on last edited by McLion
          #14

          @kshegunov
          Sorry for the delay ... was called off to work on some other software.

          OK, I moved the moveToThread and the start from the constructor to the function where the initialization takes place (when, at runtime, I got the parameters needed), as suggested to try.

          This gives me a crash at runtime (signal 11 - sigsegv - invalid memory reference).

          1 Reply Last reply
          0
          • VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by
            #15

            that's segmentation fault... did you try debugging your code?

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            McLionM 1 Reply Last reply
            0
            • VRoninV VRonin

              that's segmentation fault... did you try debugging your code?

              McLionM Offline
              McLionM Offline
              McLion
              wrote on last edited by
              #16

              @VRonin
              Working on Windows, compiling on/for Linux as well, running on eLinux device with no debugger.

              1 Reply Last reply
              0
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #17

                Can you compile for windows just for debug? or run a linux virtual machine to debug it?

                I'm sorry to be this useless but that error is quite generic. Main things to investigate:

                • Are you accessing an object through a pointer before creating it (calling new)?
                • Are you accessing an object through a pointer after it was deleted?
                • Are you trying to access a null pointer?

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                McLionM 1 Reply Last reply
                0
                • VRoninV VRonin

                  Can you compile for windows just for debug? or run a linux virtual machine to debug it?

                  I'm sorry to be this useless but that error is quite generic. Main things to investigate:

                  • Are you accessing an object through a pointer before creating it (calling new)?
                  • Are you accessing an object through a pointer after it was deleted?
                  • Are you trying to access a null pointer?
                  McLionM Offline
                  McLionM Offline
                  McLion
                  wrote on last edited by McLion
                  #18

                  @VRonin
                  Thanks for trying to help!

                  As far as I can tell everything is ok.

                  in constructor of qtgui mainwindow:

                  QThread* lolathread = new QThread;
                  LoLaWorker* lolaworker = new LoLaWorker();
                  connect(lolathread, SIGNAL(started()), lolaworker, SLOT(InitLoLaThread()));
                  connect(this, SIGNAL(TerminateLoLa()), lolaworker, SLOT(TerminateLoLaUDPsocket()));
                  .. and some more conects
                  

                  later, in function LoLaInit:

                  lolaworker->moveToThread(lolathread);
                  QMetaObject::invokeMethod(lolaworker, "InitLoLaUDPsocket", Qt::QueuedConnection, Q_ARG(QString, ip4addr), Q_ARG(quint16, port), Q_ARG(QString, location), Q_ARG(QString, name), Q_ARG(QString, MAC), Q_ARG(QString, loglevel));
                  lolathread->start();
                  

                  Anyhow, if moveToThread and start the thread are in the constructor and later emit a signal only, everything works, despite the fact that it is not immediate.

                  I start to believe that what I want is not possible.
                  I just want to have it to execute this function immediately (switching threads or whatever is needed) and following it up where it has left later (there is a queue of commands that now are worked off first, unfortunately).

                  1 Reply Last reply
                  0
                  • VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #19

                    I just want to have it to execute this function immediately

                    Then just call the function from the main thread. invokeMethod with direct connection will execute it in the calling thread anyway so I still stuggle to understand why you are doing what you are doing

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    McLionM 1 Reply Last reply
                    0
                    • VRoninV VRonin

                      I just want to have it to execute this function immediately

                      Then just call the function from the main thread. invokeMethod with direct connection will execute it in the calling thread anyway so I still stuggle to understand why you are doing what you are doing

                      McLionM Offline
                      McLionM Offline
                      McLion
                      wrote on last edited by
                      #20

                      @VRonin said in invokeMethod in other thread:

                      Then just call the function from the main thread. invokeMethod with direct connection will execute it in the calling thread anyway so I still stuggle to understand why you are doing what you are doing

                      I tried to do this - to no avail. It may well be that it's me that is doing something wrong.

                      The debug console actually shows that it seems to really directly call the functions in the other thread. However, it also ends up in a strange behavior on the debug console - dbg strings already written out are written out again - and then I again get a seg fault crash.

                      There are 3 threads: gui-main, serial and lola. I want the following to happen

                      • serial gets parameters for lola-init and emit to gui-main (master cmd-interpreter)
                      • gui-main initializes lola (works with emit, but not immediately)
                      • lola tells gui-main success or not (works with emit, but not immediately)

                      When I replace the 2 emit with direct calls, I get the crash.
                      Maybe I'm doing something wrong .. or if what I want is not possible I'll think about a different approach/solution.
                      Thanks anyway.

                      kshegunovK 1 Reply Last reply
                      0
                      • McLionM McLion

                        @VRonin said in invokeMethod in other thread:

                        Then just call the function from the main thread. invokeMethod with direct connection will execute it in the calling thread anyway so I still stuggle to understand why you are doing what you are doing

                        I tried to do this - to no avail. It may well be that it's me that is doing something wrong.

                        The debug console actually shows that it seems to really directly call the functions in the other thread. However, it also ends up in a strange behavior on the debug console - dbg strings already written out are written out again - and then I again get a seg fault crash.

                        There are 3 threads: gui-main, serial and lola. I want the following to happen

                        • serial gets parameters for lola-init and emit to gui-main (master cmd-interpreter)
                        • gui-main initializes lola (works with emit, but not immediately)
                        • lola tells gui-main success or not (works with emit, but not immediately)

                        When I replace the 2 emit with direct calls, I get the crash.
                        Maybe I'm doing something wrong .. or if what I want is not possible I'll think about a different approach/solution.
                        Thanks anyway.

                        kshegunovK Offline
                        kshegunovK Offline
                        kshegunov
                        Moderators
                        wrote on last edited by
                        #21

                        There's some confusion here. What does "immediately" mean in this context and why is this required? You can't have queued signal-slot invocation (the default) between threads executing immediately, it's not how the event loop is designed to work; and even with manual sync there's waiting for the synchronization primitive. I suspect you want to provide a blocking queued call (i.e. Qt::BlockingQueuedConnection) to wait for the target slot's end of execution, or perhaps you want a manual thread synchronization, but in any case there's no "fast and easy way", you have to make sure you don't get race conditions whatever you choose as an approach.

                        As for the segafult, as @VRonin said, track it through the debugger. This is the most common error one can get and while it usually has easily identifiable causes (i.e. buffer overflows, dangling pointers and nullptr dereferencing) there are the cases that the error might be delayed due to stack overflows in release mode with protection dummies off. In any case the cause for it can be anything, debug it!

                        Also please provide the relevant parts of the code - the signal-slot connections and a clear statement of which object is (living) in which thread when the signal emissions are happening.

                        Read and abide by the Qt Code of Conduct

                        McLionM 1 Reply Last reply
                        2
                        • kshegunovK kshegunov

                          There's some confusion here. What does "immediately" mean in this context and why is this required? You can't have queued signal-slot invocation (the default) between threads executing immediately, it's not how the event loop is designed to work; and even with manual sync there's waiting for the synchronization primitive. I suspect you want to provide a blocking queued call (i.e. Qt::BlockingQueuedConnection) to wait for the target slot's end of execution, or perhaps you want a manual thread synchronization, but in any case there's no "fast and easy way", you have to make sure you don't get race conditions whatever you choose as an approach.

                          As for the segafult, as @VRonin said, track it through the debugger. This is the most common error one can get and while it usually has easily identifiable causes (i.e. buffer overflows, dangling pointers and nullptr dereferencing) there are the cases that the error might be delayed due to stack overflows in release mode with protection dummies off. In any case the cause for it can be anything, debug it!

                          Also please provide the relevant parts of the code - the signal-slot connections and a clear statement of which object is (living) in which thread when the signal emissions are happening.

                          McLionM Offline
                          McLionM Offline
                          McLion
                          wrote on last edited by
                          #22

                          @kshegunov said in invokeMethod in other thread:

                          There's some confusion here. What does "immediately" mean in this context and why is this required?

                          I'd like to answer to this first:
                          Serial is receiving many commands in short sequence. The first is the one to initialize lola, which should be initialized before any of the other commands are executed. When everything is set up with signal-slots, the thread switches needed (gui-main to lola to make the initialization and then back to gui-main with the result of the initialization) take too long and in the meantime many of the other commands received have been executed by gui-main.

                          Of course, I can put everything in a buffer and keep it there until the initialization has taken place. In that case I'd use the signal-slot connection as it is and as it works perfectly.

                          However, I was looking for a solution to influence this sequence without the need for an additional buffer only used once for the initialization.
                          If there's no other way- OK.

                          btw. The idea of the blocking connection is what I think could do it and I'm somehow trying to do.
                          It should block gui-main from when I emit to lola to start the initialization until the answer/result is back from lola in gui-main, and then pick up on the next commands.

                          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