Unsolved signal and slots in Qthreadpool
-
MyRunnable *task = new MyRunnable(socket);
pool->start(task);
now in MyRunnable class ,only run() method is executing in one of the thread from Qthreadpool.all other slots that is have defined in that class in executing in main thread.
can i execute another slots in thread of Qthreadpool. if so,how ? -
Let's do it like a poll:
Is
MyRunnable
aQObject
?- If "yes" - What is the thread affinity of that
QObject
? - If "no" - Do regular objects have any notion of threads?
- If "yes" - What is the thread affinity of that
-
What's in the
run()
function of your MyRunnable class? If it exits it will get cleaned up. If you set it to handle signals and slots you will need an event handler.You should post some code or explain the problem with a bit more detail as there is way too much guess work to help you solve it. :)
-
@kshegunov yes myRunnable is QObject.
class MyRunnable : public QObject, public QRunnable{
};
and for checking the thread affinity,i have write:this->thread() in both run() and slot in QRunnable class.the result i am getting is same thread value in both.
it means mainthread value,threadaffinity value of run,threadaffinity value of slot are same , I can't understand how its happening ? -
@ambershark
here is my code://your code here myserver.cpp``` void myServer::setserver{ socket = new QTcpSocket(this); qDebug() << " Client connected at " << descriptor; qDebug() << "A new socket created!"; connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead())); } void MyServer::readyRead() { MyTask *mytask1 = new MyTask(socket); connect(mytask1, SIGNAL(Result(QString)), mytask1, SLOT(TaskResult(QString)), Qt::QueuedConnection); qDebug() << "Starting a new task using a thread from the QThreadPool"; QThreadPool::globalInstance()->start(mytask1); } mytask.cpp(implemented QRunnaable) MyTask::MyTask(QTcpSocket *s) { qDebug() << "MyTask()"; sock=s; } void MyTask::run() { qDebug() << "Task started"<< QThread::currentThread(); QString B= sock->readAll(); qDebug()<<"thread affinity of run:"<<this->thread(); qDebug() << "Task done"; emit Result(B); } void MyTask::TaskResult(QString B) { qDebug()<<"IN WRTIING..."<<QThread::currentThread(); QString Buffer; qDebug()<<"thread affinity of taskresult:"<<this->thread(); Buffer.append("\r\nTask result = "); Buffer.append(B); sock->write(B.toStdString().c_str()); } here what i am getting is : In run(): qDebug() << "Task started"<< QThread::currentThread(); o/p : QThread<0x101210,name ="thread<pooled>"> qDebug()<<"thread affinity of run:"<<this->thread(); o/p:thread affinity of run : QThread<0xd3800> now,in taskresult(): qDebug()<<"IN WRTIING..."<<QThread::currentThread(); o/p in writting : QThread<0xd3800> qDebug()<<"thread affinity of taskresult:"<<this->thread(); o/p : thread affinity : QThread<0xd3800> here what i want is taskresult() run in same thread as thread of run(){QThread<0x101210,name ="thread<pooled>">}.
-
@JadeN001 Ok so you are connecting your slot to that Result signal on the other thread. It will be a bit of work (I think) to get it on the thread you want it on. Normally you would just call
moveToThread()
before connecting your signal and it would be fine. However you are using a thread pool and a fire and forget runnable with no signal handler.You could stop using the QRunnable and have a thread with a QEventLoop or one that you use
moveToThread()
and it would work how you expect. I'm just not sure how to make it work with a QRunnable and a thread pool off the top of my head. If nobody else chimes in I'll do some testing tomorrow and figure it out (when I get time). -
@ambershark yeah thanks.i will try on it
-
As stated in the docs
QThreadPool
can't handle slots. You'll need to useQThread
instead -
@JadeN001 said in signal and slots in Qthreadpool:
I can't understand how its happening ?
You should be using
QThread::currentThread()
and you should in that case discover that the threadrun()
is called into is different from the onethis->thread()
returns, which incidentally is the thread your slots are called in. So your original question can be answered by answering this:Can I change the thread affinity of my object, i.e. call
moveToThread()
with the appropriate argument?If the answer's yes, then you have your solution, otherwise it means it's not possible.
-
@kshegunov i dont understand what you are trying to say.
-
That slots will be called in the thread a
QObject
is assigned to (i.e the oneQObject::thread
returns), which for that case is different from the threadQRunnable::run()
is executed in. So to do what you're asking, you have to move the object to the threadrun()
is executed in. Since withQThreadPool
you're not dealing with the threads themselves you don't have access to it, that means you can't do what you ask. In short what @VRonin wrote. -
@VRonin I want to connect multiple client to the server and want to send msg from one client to another.for this scenario i have to use qthreadpool to limit the threads.
-
@JadeN001 said in signal and slots in Qthreadpool:
for this scenario i have to use qthreadpool to limit the threads.
Not really, you just have to do some more manual work.
You can reimplement
QTcpServer::incomingConnection
to something like this:void incomingConnection(qintptr socketDescriptor) override { /* const int m_idealThreadCount = qMax(QThread::idealThreadCount(),1); QVector<QThread*> m_availableThreads; QVector<int> m_threadsLoad; */ QTcpSocket* newSocket = new QTcpSocket(this); newSocket->setSocketDescriptor(socketDescriptor); int threadIdx = m_availableThreads.size(); if (threadIdx<m_idealThreadCount) { //we can add a new thread m_availableThreads.append(new QThread(this)); m_threadsLoad.append(1); m_availableThreads.last()->start(); } else{ // find the thread with the least amount of clients and use it threadIdx = std::distance(m_threadsLoad.cbegin(),std::min_element(m_threadsLoad.cbegin(), m_threadsLoad.cend())); ++m_threadsLoad[threadIdx]; } newSocket->moveToThread(m_availableThreads.at(threadIdx)); connect(newSocket, &QTcpSocket::disconnected, newSocket, &QTcpSocket::deleteLater); connect(newSocket, &QTcpSocket::disconnected, this, [this, threadIdx]() {--m_threadsLoad[threadIdx];}); // connect other stuff to use the socket addPendingConnection(newSocket); }
-
@VRonin yeah thanks i willgo through it.for better understanding ,can you provide any example in which this approach is used.