Results 1 to 20 of 52

Thread: Qt multithreading and let the second thread update the main (UI) thread

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    May 2014
    Posts
    136
    Thanks
    72
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    MacOS X Windows

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Yeah, that is definitely one way of doing it, but I did not do it because it would introduce cyclic dependency, that is A will include B and B will include A, etc. But I will make it work anyhow. In the mean time, I tried out the entire revised code.

    The query results are coming out correctly, I am applying a qDebug() on them when they are generated and they are printed correctly. But the view is not being updated through the signal/slot. I am getting this debugging message:

    Qt Code:
    1. QObject::connect: Cannot queue arguments of type 'std::shared_ptr<QueryResult>'
    2. (Make sure 'std::shared_ptr< QueryResult >' is registered using qRegisterMetaType().)
    3.  
    4. //this starts coming from the qDebug() statement...
    5. Query result: context of a process and investigates the
    6. Query result: this proved it as because
    To copy to clipboard, switch view to plain text mode 

    How can I make it work?

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Quote Originally Posted by Cupidvogel View Post
    Yeah, that is definitely one way of doing it, but I did not do it because it would introduce cyclic dependency, that is A will include B and B will include A, etc.
    How does that introduce a dependency of any sort, much less a cyclic one?
    Neither receiver nor sender need to know about each other!

    Quote Originally Posted by Cupidvogel View Post
    Qt Code:
    1. QObject::connect: Cannot queue arguments of type 'std::shared_ptr<QueryResult>'
    2. (Make sure 'std::shared_ptr< QueryResult >' is registered using qRegisterMetaType().)
    To copy to clipboard, switch view to plain text mode 
    Seems like you have an argument type that you did not register with the Qt type system, as explained earlier by jefftee.
    Especially the shared_ptr looks strange given that you should have a "const QueryResult&" as the argument type for both signal and slot.

    So make sure that

    1) your QueryResult class has been marked with Q_DECLARE_METATYPE
    2) your QueryResult class has been registered with qRegisterMetaType()
    3) your signal has a signature with either "QueryResult" or "const QueryResult&" as its argument type
    4) your slot has a matching signature.

    Cheers,
    _

  3. #3
    Join Date
    May 2014
    Posts
    136
    Thanks
    72
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    MacOS X Windows

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Quote Originally Posted by anda_skoa View Post
    How does that introduce a dependency of any sort, much less a cyclic one?
    Neither receiver nor sender need to know about each other!
    _
    I have worked around it.

    Quote Originally Posted by anda_skoa View Post
    How does that introduce a dependency of any sort, much less a cyclic one?
    1) your QueryResult class has been marked with Q_DECLARE_METATYPE
    2) your QueryResult class has been registered with qRegisterMetaType()
    _
    How do I do it? I found an example here: http://stackoverflow.com/questions/1...eta-type-in-qt, is this how it will work?

    Qt Code:
    1. class QueryResult
    2. {
    3.  
    4. QString queryString;
    5. QString metadata;
    6. int offset;
    7. }
    8. Q_DECLARE_METATYPE( QueryResult* )
    To copy to clipboard, switch view to plain text mode 

    Where do I call the qRegisterMetaType() method on QueryTerm then? And okay, I will change the signature to const QueryAction& instead of std::shared_ptr<QueryAction>.

  4. #4
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Thanks
    13
    Thanked 153 Times in 150 Posts
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Quote Originally Posted by Cupidvogel View Post
    Where do I call the qRegisterMetaType() method on QueryTerm then? And okay, I will change the signature to const QueryAction& instead of std::shared_ptr<QueryAction>.
    You can register the meta type at any time, but obviously must be done before you attempt to use it... I typically do that early in the constructor for the main widget.

  5. #5
    Join Date
    May 2014
    Posts
    136
    Thanks
    72
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    MacOS X Windows

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Okay, I wil try to do it. But in the mean time, performance has not only not improved, it has badly worsened. I am just passing in a dummy QString to the view instead of the QueryAction object to check whether it actually works..

  6. #6
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Thanks
    13
    Thanked 153 Times in 150 Posts
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Post your code again please. I have lost track of where your overall code base has morphed since the many posts to this thread have been made. Also, please elaborate on what performance badly worsened means.

  7. #7
    Join Date
    May 2014
    Posts
    136
    Thanks
    72
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    MacOS X Windows

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Sure. It has become slow in the sense that previously, when there was a query term which resulted in a voluminous number of results, say 600~700, the UI used to kind of freeze, scrolling through the list of results (stored as QPushButtons in a QTableWidget) would become slow and dragging. But it worked correctly and more or less well. The loading size also stalled. But now the loading style is freezing completely, the cursor changes to the wheel icon (suggesting that the app has hung), and the results start updating, but soon stop, and finally, after quite some time, the view is updated with the remaining results, and the process completes.

    QueryView.hpp:

    Qt Code:
    To copy to clipboard, switch view to plain text mode 

    QueryView.cpp:

    Qt Code:
    1. QueryView::QueryView()
    2. {
    3. connect(SignalClass.get(),SIGNAL(updateViewSignal(QueryTerm&)), this, SLOT(updateView(QueryTerm&)));
    4. connect(queryButton, SIGNAL(clicked()),this, SLOT(doQuery()));
    5. }
    6.  
    7. void QueryView::doQuery()
    8. {
    9. t = new QThread()
    10. emit fSignalClass->stopExistingQuery();
    11. std::shared_ptr<QueryAction> action = std::make_shared<QueryAction>(queryTerm);
    12. action->moveToThread(t);
    13. t->start();
    14. emit fSignalClass->excuteSignal();
    15.  
    16. }
    17.  
    18. QueryView::updateView(QString& term)
    19. {
    20. ...update view with query result, currently a string for testing purpose
    21. }
    To copy to clipboard, switch view to plain text mode 

    QueryAction.hpp:

    Qt Code:
    1. class QueryAction
    2.  
    3. {
    4. QMutex m_mutex;
    5. }
    To copy to clipboard, switch view to plain text mode 

    QueryAction.cpp:

    Qt Code:
    1. QueryAction::QueryAction(QueryTerm& queryTerm): fQueryTerm(queryTerm)
    2. {
    3. connect(SignalClass.get(), SIGNAL(excuteSignal()), this, SLOT(startSearch()));
    4. connect(SignalClass.get(), SIGNAL(stopExistingQuery()), this, SLOT(stopQuery()));
    5. continueQuery = true;
    6. }
    7.  
    8. void QueryAction::startSearch()
    9. {
    10. //init cursor
    11. while (db_cursor != empty)
    12. {
    13. ...get query result
    14. QMutexLocker locker(&m_mutex);
    15. if (continueQuery)
    16. emit fSignalClass->updateViewSignal(aResult.asQString());
    17. else
    18. break;
    19. }
    20. }
    21.  
    22. void QueryAction::stopQuery()
    23. {
    24. QMutexLocker locker(&m_mutex);
    25. continueQuery = false;
    26. }
    To copy to clipboard, switch view to plain text mode 

  8. #8
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Thanks
    13
    Thanked 153 Times in 150 Posts
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Your use of pointers in the emit'ing of signals for a different class/object seem unnatural to me. Not sure if that's a performance problem or not, but IMHO you should rework your signal/slot usage so that each class emits a signal when it has something that others may be interested in.

    So in your example above, updateViewSignal should be a signal defined by QueryAction. All it needs to do when it has new data that anyone may be interested in is:

    Qt Code:
    1. emit updateViewSignal(aResult.asQString());
    To copy to clipboard, switch view to plain text mode 

    The way you have your signals setup now, the object that wants to emit the signal has to have a pointer to the object you want to receive the signal, which totally undoes the abstraction that signals/slots provides.

  9. #9
    Join Date
    May 2014
    Posts
    136
    Thanks
    72
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    MacOS X Windows

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Okay. So suppose the updateViewSignal signal belongs to QueryAction and it emits it like you said. How do the view class listen to it?

  10. #10
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Thanks
    13
    Thanked 153 Times in 150 Posts
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Same way any other signal/slot connection works. To make any connect you need the address of the sender and receiver objects and the name/signature of the signal and the name/signature of the receiving slot.

  11. #11
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Quote Originally Posted by Cupidvogel View Post
    How do I do it? I found an example here: http://stackoverflow.com/questions/1...eta-type-in-qt, is this how it will work?

    Qt Code:
    1. class QueryResult
    2. {
    3.  
    4. QString queryString;
    5. QString metadata;
    6. int offset;
    7. }
    8. Q_DECLARE_METATYPE( QueryResult* )
    To copy to clipboard, switch view to plain text mode 
    No, the type itself:
    Qt Code:
    1. Q_DECLARE_METATYPE(QueryResult)
    To copy to clipboard, switch view to plain text mode 

    Quote Originally Posted by Cupidvogel View Post
    And okay, I will change the signature to const QueryAction& instead of std::shared_ptr<QueryAction>.
    You mean QueryResult, right?

    Quote Originally Posted by jefftee View Post
    Your use of pointers in the emit'ing of signals for a different class/object seem unnatural to me.
    Indeed, already pointed that out, only to be told that my advice was worked around :-/

    Cheers,
    _
    Last edited by anda_skoa; 19th April 2015 at 22:27.

  12. #12
    Join Date
    May 2014
    Posts
    136
    Thanks
    72
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    MacOS X Windows

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Sorry guys for the late reply. I did as you said, moved all signals and slots to respective classes instead of relying on Signal Class as I was doing. Still the same performance, app hangs badly, the loading symbol completely freezes, but after some time all query results do show up on the UI. Here is my code:

    QueryView.hpp:

    Qt Code:
    1. class QueryView
    2. {
    3. QThread *t;
    4. QueryAction *action;
    5. signals:
    6. void excuteSignal();
    7. void stopExistingQuery();
    8. }
    To copy to clipboard, switch view to plain text mode 

    QueryView.cpp:

    Qt Code:
    1. QueryView::QueryView()
    2. {
    3. connect(SignalClass.get(),SIGNAL(updateViewSignal(QueryTerm&)), this, SLOT(updateView(QueryTerm&)));
    4. connect(queryButton, SIGNAL(clicked()),this, SLOT(doQuery()));
    5. }
    6.  
    7. void QueryView::doQuery()
    8. {
    9. t = new QThread()
    10. emit stopExistingQuery();
    11. action = new QueryAction(queryTerm);
    12.  
    13. connect(this,SIGNAL(excuteSignal()), fSearchAction, SLOT(startQuery()));
    14. connect(this,SIGNAL(stopExistingQuery()), fSearchAction, SLOT(stopQuery()));
    15. connect(fSearchAction, SIGNAL(updateViewSignal(QString)),this, SLOT(updateView(QString)));
    16.  
    17. action->moveToThread(t);
    18. t->start();
    19. emit excuteSignal();
    20.  
    21. }
    22.  
    23. QueryView::updateView(QString& term)
    24. {
    25. ...update view with query result, currently a string for testing purpose, as a QPushButton, forming a series of buttons in a QTableWidget
    26. }
    To copy to clipboard, switch view to plain text mode 

    QueryAction.hpp:

    Qt Code:
    1. class QueryAction
    2.  
    3. {
    4. QMutex m_mutex;
    5.  
    6. signals:
    7. void updateSearchView2(QString);
    8. }
    To copy to clipboard, switch view to plain text mode 

    QueryAction.cpp:

    Qt Code:
    1. QueryAction::QueryAction(QueryTerm& queryTerm): fQueryTerm(queryTerm)
    2. {
    3. QMutexLocker locker(&m_mutex);
    4. continueQuery = true;
    5. }
    6.  
    7. void QueryAction::startSearch()
    8. {
    9. //init cursor
    10. while (db_cursor != empty)
    11. {
    12. ...get query result
    13. QMutexLocker locker(&m_mutex);
    14. if (continueQuery)
    15. emit updateViewSignal(aResult.asQString());
    16. else
    17. break;
    18. }
    19. }
    20.  
    21. void QueryAction::stopQuery()
    22. {
    23. QMutexLocker locker(&m_mutex);
    24. continueQuery = false;
    25. }
    To copy to clipboard, switch view to plain text mode 

  13. #13
    Join Date
    Dec 2009
    Location
    New Orleans, Louisiana
    Posts
    791
    Thanks
    13
    Thanked 153 Times in 150 Posts
    Qt products
    Qt5
    Platforms
    MacOS X

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Post a minimal compilable example please so that I can recreate and/or step through your code and see what's going on.

  14. #14
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Quote Originally Posted by Cupidvogel View Post
    Here is my code:
    No, it is not.
    That is the same code snippets with the same problems pointed out several times.

    Cheers,
    _

  15. #15
    Join Date
    May 2014
    Posts
    136
    Thanks
    72
    Qt products
    Qt3 Qt4 PyQt3 PyQt4
    Platforms
    MacOS X Windows

    Default Re: Qt multithreading and let the second thread update the main (UI) thread

    Umm, like what? You mentioned that the signals and slots should not be from a separate class. I did that. What else needs to be done? I am currently passing a simple QString to display in the UI

Similar Threads

  1. Replies: 1
    Last Post: 28th March 2012, 18:58
  2. Replies: 5
    Last Post: 22nd February 2011, 21:21
  3. Replies: 9
    Last Post: 28th November 2009, 20:31
  4. Replies: 16
    Last Post: 7th October 2009, 08:17
  5. Replies: 6
    Last Post: 29th April 2009, 18:17

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.