Page 3 of 3 FirstFirst 123
Results 41 to 52 of 52

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

  1. #41
    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 

  2. #42
    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.

  3. #43
    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?

  4. #44
    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.

  5. #45
    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. Will try this.


    Added after 7 minutes:


    Will this work?

    Qt Code:
    1. void QueryView::doQuery()
    2. {
    3. t = new QThread();
    4. std::shared_ptr<QueryAction> action = std::make_shared<QueryAction>(queryTerm);
    5. connect(this, SIGNAL(stopExistingQuery()), action, SLOT(stopQuery());
    6. connect(this, SIGNAL(excuteSignal()), action, SLOT(startSearch());
    7. emit stopExistingQuery();
    8. action->moveToThread(t);
    9. t->start();
    10. emit excuteSignal();
    11. }
    To copy to clipboard, switch view to plain text mode 

    Essentially I have moved both signals from SignalClass to the view, and for each instance of the QueryAction class being generated, I am connecting the signal/slots for start and stop querying. Will this be better, even if it works?
    Last edited by Cupidvogel; 19th April 2015 at 19:54.

  6. #46
    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 23:27.

  7. #47
    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 

  8. #48
    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.

  9. #49
    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,
    _

  10. #50
    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

  11. #51
    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
    Umm, like what?
    You posted this:
    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 
    And you would like us to believe that is the actual code you are using?
    With SignalClass.get(), which you claim have removed, with reference as signal argument types which you have been told won't work, with signal signatures not matching slot signatures, with variable names not matching (action vs. fSearchAction)?

    How stupid do you think we are?

    Cheers,
    _

  12. #52
    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, wait, why would I ask you for help if I considered you stupid? I forgot to remove the SignalClass from that part of the code because I was editing my copy paste from my previous post and overlooked that part. Obviously this is not the exact code I have, there are lots of variable definitions, array populating, my project specific code (which I am forbidden to post for confidentiality reasons) etc which don't belong to the ambit of this problem and thus I did not include here (for starters, my QueryAction header class is 8 lines long, in reality it is around 35~40 lines.) Fo example after the querying is complete I have the action class emit a signal which feeds in to a slot in the view that shows a message like 'Total number of query results is <some_number>', but I did not include it here because it doesn't add anything to the problem scope. I have changed some of my variable names here so that I had to do less typing (for example I renamed fSearchAction to action). It's only after you said that the Signal Class mapper might be causing the problem did I go ahead and change it (while editing I forgot to edit one part). In essence this is the summary of the entire process I am currently running. Why on earth would I not try out what you are suggesting and yet ask you for further suggestions?

    If it helps, here is my latest code (statutory disclaimer: this code cannot be and is not considered completely representative of my entire project, not does it purport to be. It's aim is to provide a high level overview of my problem, and is open to request [please] for more information, that will be provided subject to the terms and conditions of the company I am working for in capacity of a software engineer to make a product, with an ardent expectation that it will be sufficient to experienced Qt programmers in this forum to be able to offer advice and suggestion to improve it. Viewers' discretion is advised.)

    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(queryButton, SIGNAL(clicked()),this, SLOT(doQuery()));
    4. }
    5.  
    6. void QueryView::doQuery()
    7. {
    8. t = new QThread()
    9. emit stopExistingQuery();
    10. action = new QueryAction(queryTerm);
    11.  
    12. connect(this,SIGNAL(excuteSignal()), action, SLOT(startQuery()));
    13. connect(this,SIGNAL(stopExistingQuery()), action, SLOT(stopQuery()));
    14. connect(action, SIGNAL(updateViewSignal(QString)),this, SLOT(updateView(QString)));
    15.  
    16. action->moveToThread(t);
    17. t->start();
    18. emit excuteSignal();
    19.  
    20. }
    21.  
    22. QueryView::updateView(QString term)
    23. {
    24. ...update view with query result, currently a string for testing purpose, as a QPushButton, forming a series of buttons in a QTableWidget
    25. }
    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 updateViewSignal(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::startQuery()
    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 
    Last edited by Cupidvogel; 21st April 2015 at 13:34.

Similar Threads

  1. Replies: 1
    Last Post: 28th March 2012, 19:58
  2. Replies: 5
    Last Post: 22nd February 2011, 22:21
  3. Replies: 9
    Last Post: 28th November 2009, 21:31
  4. Replies: 16
    Last Post: 7th October 2009, 09:17
  5. Replies: 6
    Last Post: 29th April 2009, 19: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.