Results 1 to 8 of 8

Thread: How to Have a class run in a separate thread.

  1. #1
    Join Date
    Aug 2013
    Posts
    4
    Qt products

    Default How to Have a class run in a separate thread.

    This question is related to Pyside 4

    I am trying to accomplish something that at first seemed like a common task but maybe I am overlooking some technical problem with it.

    I have a simple class for "database". The init has a few lines of code for connecting to the database, and then the class has various functions for standard read and write operations and a few special cases etc. In the past, I would initialize the database class, and then just use its functions to accomplish basic IO. The issue is that the database connection in the init, as well as the IO methods, can take a second or two, leaving the main GUI frozen. In the past I have used the qthread class for this, and placed code in the run() method for either a one-shot running of the code, or a periodic (once a minute or something) running of some code. In this case, though, I want the thread to just run as long as the instance of the class is running. Or to be more specific, the thread should run for initialization of the database class as well as whenever I call a method of the database class. I have searched for this and found suprisingly few results for something that seems like it would be a common desire. (to have one instance run as a thread)

    Thanks.

  2. #2
    Join Date
    Feb 2013
    Location
    India
    Posts
    153
    Thanks
    27
    Thanked 18 Times in 18 Posts
    Qt products
    Qt4 Qt5 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: How to Have a class run in a separate thread.

    Quote Originally Posted by sona1111 View Post
    This question is related to Pyside 4

    I am trying to accomplish something that at first seemed like a common task but maybe I am overlooking some technical problem with it.

    I have a simple class for "database". The init has a few lines of code for connecting to the database, and then the class has various functions for standard read and write operations and a few special cases etc. In the past, I would initialize the database class, and then just use its functions to accomplish basic IO. The issue is that the database connection in the init, as well as the IO methods, can take a second or two, leaving the main GUI frozen. In the past I have used the qthread class for this, and placed code in the run() method for either a one-shot running of the code, or a periodic (once a minute or something) running of some code. In this case, though, I want the thread to just run as long as the instance of the class is running. Or to be more specific, the thread should run for initialization of the database class as well as whenever I call a method of the database class. I have searched for this and found suprisingly few results for something that seems like it would be a common desire. (to have one instance run as a thread)

    Thanks.
    hello sona,

    You can use QThread for this kind of problem.
    If your database class is a separate class, the you can use moveToThread

    Qt Code:
    1. class *a = new class;
    2. QThread *thread = new QThread;
    3. a->moveToThread(thread);
    4. thread->start();
    To copy to clipboard, switch view to plain text mode 

    the above code will now run the object a in a different thread.

    or you can create your own thread by using QThread
    refer http://doc.qt.digia.com/4.6/threads-...the-sql-module

  3. #3
    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: How to Have a class run in a separate thread.

    Or do what you have done so far and just don't exit from run().

    Either using a loop or calling exec() to start the thread's event loop.

    Cheers,
    _

  4. #4
    Join Date
    Aug 2013
    Posts
    4
    Qt products

    Default Re: How to Have a class run in a separate thread.

    So it still lags when connecting and retrieving data using move to thread even though with move to thread following this example for my program almost line by line: http://stackoverflow.com/questions/1...le-application

    (as it is the only example of this I can find)

    However, getting the thread id in the DB class and the main class yields the same ID, so I must be doing something wrong. Does anyone have a small python example of movetothread?

    thanks.

  5. #5
    Join Date
    Aug 2013
    Posts
    4
    Qt products

    Default Re: How to Have a class run in a separate thread.

    I still have had no luck getting this to work. In all examples I can find, the only part of the object that runs in a thread is a single method, not other parts of the class. For example in the code from SO:

    Qt Code:
    1. from PySide import QtCore
    2. import time
    3. import sys
    4.  
    5.  
    6. # Subclassing QObject and using moveToThread
    7. # http://labs.qt.nokia.com/2007/07/05/qthreads-no-longer-abstract/
    8. class SomeObject(QtCore.QObject):
    9.  
    10. finished = QtCore.Signal()
    11.  
    12. def longRunning(self):
    13. count = 0
    14. while count < 5:
    15. time.sleep(1)
    16. print "Increasing"
    17. count += 1
    18. self.finished.emit()
    19.  
    20.  
    21.  
    22.  
    23.  
    24.  
    25. def usingMoveToThread():
    26. app = QtCore.QCoreApplication([])
    27. objThread = QtCore.QThread()
    28. obj = SomeObject()
    29. obj.moveToThread(objThread)
    30. obj.finished.connect(objThread.quit)
    31. objThread.started.connect(obj.longRunning)
    32. objThread.finished.connect(app.exit)
    33. objThread.start()
    34. sys.exit(app.exec_())
    35.  
    36.  
    37.  
    38. if __name__ == "__main__":
    39.  
    40. usingMoveToThread()
    To copy to clipboard, switch view to plain text mode 

    This is really only calling the "longrunning" method in another thread, and other operations that I could call on the class would seem to be required to call "start" on the class again and make another instance, then call another method in a separate thread which for the database would mean calling the constructor again and reconnecting to the database again. I don't mind if database operations get queued in the worker thread, actually that would be preferable because the throughput to a single DB is not going to increase be trying to connect twice anyway. I just want to use the DB instance with values it returns going to the GUI when it is done pulling the data (without freezing the GUI during the network operations). Because I already had the class/object set up correctly to work I thought it would make sense to do it this way but maybe what I am saying is impossible. Here is an example of what I am looking for:

    Suppose I have this class (hastily written so it might not be completely perfect):
    Qt Code:
    1. class DBcore(QtCore.QObject):
    2.  
    3.  
    4. def __init__(self, parent=None):
    5. super(DBcore, self).__init__(parent)
    6. connection = pymongo.MongoClient(connection_string)
    7. database = connection.avdb
    8. self.db = database
    9.  
    10.  
    11.  
    12. def showDatabaseTable(self, tableToLoad):
    13.  
    14. for q, row in enumerate(self.requests.find()):
    15. table_rows += 1
    16. if q == 0:
    17. for col in row:
    18. table_cols += 1
    19. time.sleep(0)
    20. else:
    21. pass
    22.  
    23. self.retr_table_cols = table_cols
    24. self.retr_table_rows = table_rows
    25. self.retr_data = self.requests.find().sort([('_id',1)])
    26.  
    27.  
    28. return (self.retr_table_cols, self.retr_table_rows, self.retr_data)
    To copy to clipboard, switch view to plain text mode 

    In my GUI object or somewhere in a higher level, I would put "DB = DBcore()" and then either use the functions like DB.showDatabaseTable(clients) or just use mongoDB in a random write or something like DB.db.clients.insert({"name":"John"}). In both of these cases I would like the operation to run in a separate thread automatically, because it is using the "DB" object. Is this possible or unheard of?

    Thanks.

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to Have a class run in a separate thread.

    "Classes" don't "run in threads". Classes are just code. If you call some function from thread A it will run in thread A, if you call it from thread B, it will run in thread B. When QThread is started, it calls its run() method in a new thread, that's why "run" executes in context of that thread. If you want other methods to be ran in that thread, call them from run() or use signal-slot connections, move the object to the desired thread and make sure the event loop is running in that thread. Then all slots when invoked as such will be ran in the context of the thread owning the object.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Aug 2013
    Posts
    4
    Qt products

    Default Re: How to Have a class run in a separate thread.

    I am having trouble understanding how the "event loops" are supposed to run in a similar manner to classes. (note for this post and my previous one, I am well aware that the code in a class does not do anything by itself, when I say "class" in this case, I mean one instance of an object from the class I wrote. I thought this was a common concept, but maybe calling it a class instead of an object confused people.) For example, In the above class example, I have a handle on the DB object (an instance created from the mongodb 'driver'), anytime I call an operation on this, I would like it to run in a separate thread. (I am making it simpler so maybe it will be easier to understand) First of all, what does an "event loop" really mean? Is it explained somewhere? Is it just one literal while loop which runs until you kill the thread? If it is run like that, how are you supposed to call the methods on the DB object from the GUI? are you supposed to emit a signal with a string and try to think of every possible method you will call and define if/then's for it? (if so, this is a ridiculous way to program anything) Are you supposed to emit a signal with a large amount of strings and use a bunch of getattr statements to append them to the DB object? It still sounds like the wrong way to go.

    If I am still missing something major here, please tell me. Otherwise, can anyone make a demo for this? A single window with a few buttons that call DB.insert, DB.find etc when you press them, but do not freeze the gui when you click them.

    Thank you for reading.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: How to Have a class run in a separate thread.

    Quote Originally Posted by sona1111 View Post
    I am having trouble understanding how the "event loops" are supposed to run in a similar manner to classes.
    They are not since classes (and objects) do not "run" in any way. The only thing that an object does is that it "exists".

    An event loop is basically this code:

    Qt Code:
    1. while(!stopCondition) {
    2. processEvents();
    3. }
    To copy to clipboard, switch view to plain text mode 

    with "processEvents" being a call which takes an event out of a queue and processes it.

    You can compare "objects" to books and threads to people reading books. If you have two books, it is not true that there are separate people reading them just because they are different books. When one book has a reference to another book, reading that book does not require a new person -- the initial person just puts the original book aside, takes the other one, reads what needs to be read, puts that book aside and comes back to the first one. In this situation the process of reading the first book is "frozen" for the duration of reading the other book. The same applies if the book refers to itself -- you open the book on a different page, read what you need and go back to the previous context. The basic principle is that you can read only one line of text from one book at a time and that you read lines in sequence or can jump to a different line and start reading there.

    With multiple people (multiple threads) they can read two books at the same time or they even can read different pages of the same book at the same time (however with the latter, they have to be more careful not to disturb each other) or even read the same lines of the same book concurrently provided if some conditions are met (they can both see the text and they "take notes" of the content on different sheets of paper instead of say... writing on the margins of the book directly).

    If you read book A and you want some information from book B but you want to save some time and continue reading book A, then it doesn't happen automatically that your friend reads book B for you and hands over his notes related to what you need from the other book. You have to tell the guy "hey my good friend, could you read page 42 from book B for me and tell me what it is about?" thus you send a message to your friend asking him for a favour. If you do that in a wrong moment you might disturb your friend the same way as he would make you very angry if he tried to give you the information you needed while you were taking your own notes and you forgot half of what you wanted to write because of him talking to you or worse writing down his answers on your piece of paper over the text you have already written. You and your friend need to synchronize how you exchange information.

    This is exactly the same with threads. If you want a worker thread to do something for you then you need to ask for it and when the response is ready the other thread has to know how to return that info to you. Qt provides two built-in mechanisms for that -- events and signals and slots and apart from those two you can build your own mechanisms based on direct data exchange provided you do proper synchronization using synchronization primitives such as mutexes and wait conditions.

    Basically you will either have to wait until your friend finishes reading what you wanted him to read for you (which usually defeats the whole purpose of cooperating with a different "person" as you might have as well read that other book yourself then) or you need a way to be notified about the data when it is ready.
    Last edited by wysota; 29th August 2013 at 06:49.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. OpenGL rendering in separate thread, Qt 5.0.1
    By jaf in forum Qt Programming
    Replies: 3
    Last Post: 27th October 2015, 23:03
  2. GUI Updates from separate Thread
    By sa5webber in forum Newbie
    Replies: 5
    Last Post: 16th June 2012, 20:08
  3. Put in a separate thread a method of a class
    By franco.amato in forum Qt Programming
    Replies: 0
    Last Post: 19th March 2010, 23:45
  4. new QWidget in separate thread
    By magland in forum Qt Programming
    Replies: 15
    Last Post: 7th February 2008, 12:32
  5. handling paintGL in a separate thread
    By al101 in forum Qt Programming
    Replies: 1
    Last Post: 15th May 2007, 17:04

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.