Does moveToThread() creates a thread?
-
@MokJ said in Does moveToThread() creates a thread?:
Does moveToThread() creates a new thread ??
no, since you already need to pass a QThread instance to moveToThread()
What it means when we say move an object to the thread?
Have you already read the docs?
Why do you want to call this method? Whats your usecase?@raven-worx thanks for quick response
I'm trying to build a client server chat kind of thing, and on server side I have used movertothread().
The object I'm moving is a class in which I'm doing setSocketDescriptor() and reading and writing into the socket.
So in void incommingConnection() I'm moving that class by moveToThread().
Void server::incommingconnection(qintptr sd){
Worker class* worker= new workerclass();
Qthread *thread=new Qthread();
Worker->moveToThread(thread);
thread->start();}
It works fine and very smooth.
But I was thinking about efficiency, if I connect 100 clients , will my server allow 100 threads to get created? -
Hello,
No, it doesn't. You need a QThread in which you move the object.
Here is the worker object pattern example from Qt, from QThread documentation. You can see that there is a
QThread workerThread;
in the class Controller, which creates the Worker object and then move it in workerThread.class Worker : public QObject { Q_OBJECT public slots: void doWork(const QString ¶meter) { QString result; /* ... here is the expensive or blocking operation ... */ emit resultReady(result); } signals: void resultReady(const QString &result); }; class Controller : public QObject { Q_OBJECT QThread workerThread; public: Controller() { Worker *worker = new Worker; worker->moveToThread(&workerThread); connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); connect(this, &Controller::operate, worker, &Worker::doWork); connect(worker, &Worker::resultReady, this, &Controller::handleResults); workerThread.start(); } ~Controller() { workerThread.quit(); workerThread.wait(); } public slots: void handleResults(const QString &); signals: void operate(const QString &); };
-
@Gojir4 thanks just having this doubt, please bear with me , so if I connect 100 sockets as clients to my server, how many threads are being generated?
I'm doing QTcpSocket *socket=new QTcpSocket();
in worker class.@MokJ I don't think that's the best option to create a dedicated thread for every client.
Another approach can be to run the server in a dedicated thread and use the asynchonous system which is already provided with signals-slots mechanism. For about 100 clients it could be enough, but it depends of the frequency of your requests.
Or maybe to create a temporary thread handling each single request. Using QRunnable and QThreadPool.
In both case, you can have a list of objects representing your clients, in the Main thread (GUI), and synchronize these objects according to your communication coming from the "Server" thread, using signal-slots.
Anyway, that's only some suggestions, and it depends a lot of the goal of your application and the number of requests coming from clients, I'm not a specialist in this domain so it could be better to wait a reply from somebody which have more knowledge on this subjet :)
-
Did you already see this example: Network Chat Example
-
@Gojir4 thanks just having this doubt, please bear with me , so if I connect 100 sockets as clients to my server, how many threads are being generated?
I'm doing QTcpSocket *socket=new QTcpSocket();
in worker class.@MokJ said in Does moveToThread() creates a thread?:
so if I connect 100 sockets as clients to my server, how many threads are being generated?
That depends on your code. If you spin a thread for each client, then 100 clients means 100 threads. What one usually does when dealing with connection-heavy/high-throughput situation is to put a middleman that does the bookkeeping of which connection goes to what handler - the so called broker pattern. However it's rather complicated for the typical use case.
-
thankk you @Gojir4 and @kshegunov , I was thinking about putting some other design for server, I want my server to handle more clients with minimum number of threads, Whats happening now is everytime a new connection is available , server generates new thread as i have created an object of worker thread and QThread() in incommingConnection().
So i mean if there are any sort of suggestions , appreciated. Thanks again. -
thankk you @Gojir4 and @kshegunov , I was thinking about putting some other design for server, I want my server to handle more clients with minimum number of threads, Whats happening now is everytime a new connection is available , server generates new thread as i have created an object of worker thread and QThread() in incommingConnection().
So i mean if there are any sort of suggestions , appreciated. Thanks again.Use a thread pool (basically start X number of threads beforehand) and move the objects to one of the threads in the pool "semi-randomly".
-
Use a thread pool (basically start X number of threads beforehand) and move the objects to one of the threads in the pool "semi-randomly".
@kshegunov Lol someone else just basically asked this exact question here and I made the thread pool comment there. As I read this was about to do the same here and you beat me to it. Great minds think alike and all that. ;)
-
@kshegunov , yeah but I'm more thinking about non QThreadpool era , I mean want to do it without using QThreadpool.
@ambershark , I read that post you're referring to and I created a small code based on that. But I think doing it without QThreadpool can bring some more understanding about QThreads . -
@kshegunov , yeah but I'm more thinking about non QThreadpool era , I mean want to do it without using QThreadpool.
@ambershark , I read that post you're referring to and I created a small code based on that. But I think doing it without QThreadpool can bring some more understanding about QThreads .I didn't mean
QThreadPool
. A thread pool is a concept first, and only then it's a class.
Consider something like:class Server : public QTcpServer { Q_OBJECT public: Server(QObject * = nullptr); ~Server() override; protected: void incommingConnection(qintptr) override; private: int counter; QVector<QThread> pool; static int threadsCount; };
int Server::threadsCount = 5; Server::Server(QObject * parent) : QTcpServer(parent), counter(0), pool(threadsCount) { for (int i = 0; i < threadsCount; i++) pool[i].start(); } Server::~Server() { for (int i = 0; i < threadsCount; i++) { pool[i].quit(); pool[i].wait(); } } void Server::incommingConnection(qintptr descriptor) { Worker * worker = new Worker(); QThread * thread = &pool[counter++ % threadsCount]; QObject::connect(worker, &Worker::finished, worker, &QObject::deleteLater); QObject::connect(thread, &QThread::finished, worker, &QObject::deleteLater); worker->moveToThread(thread); // Initialize the socket in the correct thread QMetaObject::invokeMethod(worker, [worker, descriptor] () -> void { QTcpSocket * socket = new QTcpSocket(worker); socket->setSocketDescriptor(descriptor); worker->setSocket(socket); }); }
Adjust the worker object as needed to make the above work.
-
I didn't mean
QThreadPool
. A thread pool is a concept first, and only then it's a class.
Consider something like:class Server : public QTcpServer { Q_OBJECT public: Server(QObject * = nullptr); ~Server() override; protected: void incommingConnection(qintptr) override; private: int counter; QVector<QThread> pool; static int threadsCount; };
int Server::threadsCount = 5; Server::Server(QObject * parent) : QTcpServer(parent), counter(0), pool(threadsCount) { for (int i = 0; i < threadsCount; i++) pool[i].start(); } Server::~Server() { for (int i = 0; i < threadsCount; i++) { pool[i].quit(); pool[i].wait(); } } void Server::incommingConnection(qintptr descriptor) { Worker * worker = new Worker(); QThread * thread = &pool[counter++ % threadsCount]; QObject::connect(worker, &Worker::finished, worker, &QObject::deleteLater); QObject::connect(thread, &QThread::finished, worker, &QObject::deleteLater); worker->moveToThread(thread); // Initialize the socket in the correct thread QMetaObject::invokeMethod(worker, [worker, descriptor] () -> void { QTcpSocket * socket = new QTcpSocket(worker); socket->setSocketDescriptor(descriptor); worker->setSocket(socket); }); }
Adjust the worker object as needed to make the above work.
@kshegunov Thanks very much , I'll try it this way
-
@raven-worx thanks for quick response
I'm trying to build a client server chat kind of thing, and on server side I have used movertothread().
The object I'm moving is a class in which I'm doing setSocketDescriptor() and reading and writing into the socket.
So in void incommingConnection() I'm moving that class by moveToThread().
Void server::incommingconnection(qintptr sd){
Worker class* worker= new workerclass();
Qthread *thread=new Qthread();
Worker->moveToThread(thread);
thread->start();}
It works fine and very smooth.
But I was thinking about efficiency, if I connect 100 clients , will my server allow 100 threads to get created? -
@FirMoon said in Does moveToThread() creates a thread?:
No, you use threadpool instead.
If you mean
QThreadPool
, no you don't! Sockets (QAbstractSocket
) can be created and used only in one single thread, which is granularity whichQThreadPool
doesn't allow. Moreover once the socket object is created it can't be moved to another thread (directly).QThreadPool
operates on atomic work units (QRunnable
) and there's no guarantee in which thread from the pool the unit is going to be executed in.