How QTcpSocket Asynchronous return taskreult to each socket
-
Hi,
I follow the website to implement the Asynchronous Task for socket.void MyClient::readyRead() { qDebug() << "MyClient::readyRead()"; qDebug() << socket->readAll(); // Time consumer MyTask *mytask = new MyTask(); mytask->setAutoDelete(true); // using queued connection connect(mytask, SIGNAL(Result(int)), this, SLOT(TaskResult(int)), Qt::QueuedConnection); qDebug() << "Starting a new task using a thread from the QThreadPool"; // QThreadPool::globalInstance() returns global QThreadPool instance QThreadPool::globalInstance()->start(mytask); } // After a task performed a time consuming task, // we grab the result here, and send it to client void MyClient::TaskResult(int Number) { QByteArray Buffer; Buffer.append("\r\nTask result = "); Buffer.append(QString::number(Number)); socket->write(Buffer); }
My problem is the task result will send to each client that is waiting for the task result
For Example:
The task result needs 3s to finish and return. Now, there are multiple clients are created.
The 1st client requires task results at 0s.
The 2nd client requires task results at 1s.
At the 3s, The task finish sends the signal Result() of the 1st client.
The 1st and 2nd client will receive the signal and do the socket->write()It's there a way to avoid this situation?
My only idea is to pass socket information to the task.
When the task is finished, it passes the required socket information to the client.
The client should check the task result which is it required or not by socket information.Is there any other better method or advice?
-
Hi,
You should map your tasks with the socket it shall report to. That way when the task is done you can retrieve the appropriate socket and then write the result to it.
-
Hi,
I follow the website to implement the Asynchronous Task for socket.void MyClient::readyRead() { qDebug() << "MyClient::readyRead()"; qDebug() << socket->readAll(); // Time consumer MyTask *mytask = new MyTask(); mytask->setAutoDelete(true); // using queued connection connect(mytask, SIGNAL(Result(int)), this, SLOT(TaskResult(int)), Qt::QueuedConnection); qDebug() << "Starting a new task using a thread from the QThreadPool"; // QThreadPool::globalInstance() returns global QThreadPool instance QThreadPool::globalInstance()->start(mytask); } // After a task performed a time consuming task, // we grab the result here, and send it to client void MyClient::TaskResult(int Number) { QByteArray Buffer; Buffer.append("\r\nTask result = "); Buffer.append(QString::number(Number)); socket->write(Buffer); }
My problem is the task result will send to each client that is waiting for the task result
For Example:
The task result needs 3s to finish and return. Now, there are multiple clients are created.
The 1st client requires task results at 0s.
The 2nd client requires task results at 1s.
At the 3s, The task finish sends the signal Result() of the 1st client.
The 1st and 2nd client will receive the signal and do the socket->write()It's there a way to avoid this situation?
My only idea is to pass socket information to the task.
When the task is finished, it passes the required socket information to the client.
The client should check the task result which is it required or not by socket information.Is there any other better method or advice?
@Shao I don't understand your description (it is really unclear). I also don't understand your code: why do you call readAll() to output it to qDebug?! After readAll() there is no data anymore to read - don't you want to use it? I also don''t understand why you're creating a new MyTask each time readyRead() is called! readyRead() can be called several times for one package sent! I also don't see how you're handling different client connections...
Please try to explain better what you actually want to achieve.
-
Hi @jsulm
Here is my code
ControlServer.cpp
#include "controlserver.h" #include <iostream> using namespace std; ControlServer::ControlServer(int _port, QObject *parent):port(_port) { setParent(parent); } bool ControlServer::startServer() { bool ret = this->listen(QHostAddress::Any, port); if(ret){ cout << "start control server"<<endl; } else{ cout << "control server start failed"<<endl; } return ret; } void ControlServer::bindProgrammer(PROGRAMMER *_programmer) { mProgrammer = _programmer; } // ****create client for each connection**** void ControlServer::incomingConnection(qintptr handle) { cout << handle<<endl; ControlSocket *mControlSocket = new ControlSocket(this); mControlSocket->setSocket(handle); mControlSocket->setProgrammer(mProgrammer); // serial port device }
ControlSocket.cpp
ControlSocket::ControlSocket(QObject *parent):MySocket(parent) { QThreadPool::globalInstance()->setMaxThreadCount(5); } void ControlSocket::setProgrammer(PROGRAMMER *_programmer) { mProgrammer = _programmer; } // **** readyRead create and assign task void ControlSocket::readyRead() { QByteArray data = this->socket->readAll(); // Time consumer MyControlTask *mControlTask = new MyControlTask(mProgrammer, data); mControlTask->setAutoDelete(true); connect(mControlTask, SIGNAL(result(QByteArray)), this, SLOT(TaskResult(QByteArray)), Qt::QueuedConnection); QThreadPool::globalInstance()->start(mControlTask); cout << data.data() <<endl; } void ControlSocket::TaskResult(QByteArray data) { cout << __func__ << data.data()<<endl; data.push_front("echo:"); socket->write(data); }
MyControlTask.cpp
#include "mycontroltask.h" #include <iostream> #include <QThread> using namespace std; MyControlTask::MyControlTask(PROGRAMMER *_programmer, QByteArray _cmd, QObject *parent):mProgrammer(_programmer), mCmd(_cmd) { connect(this, SIGNAL(transferToProgrammer(QByteArray)), mProgrammer, SLOT(sendToUart(QByteArray))); connect(mProgrammer, SIGNAL(EchoToTask(QByteArray)), this, SLOT(ProgrammerToTask(QByteArray))); } void MyControlTask::ProgrammerToTask(QByteArray data) { cout <<"ProgrammerToTask" << data.data()<<endl; emit(result(data)); } void MyControlTask::run() { cout << "Run:" << mCmd.data()<<endl; emit(transferToProgrammer(mCmd)); //emit signal to trigger // since the mProgrammer is also QThread::usleep(10000000); }
The main step in controlscoket as below
- read data and store
- create task with mProgrammer (a SerialPort device) and data (each socket client will connect to the same mProgrammer(serialPort Device)
- connect mProgrammer result signal to this task Result
- start task to parsing data and do something depending on the decoding result
- wait to TaskResult and socket write to client with the result
I am confused in step 2~5.
For each data, I will create a task to do something.
If the first task is unfinished, I create the second task.
And then the first task finsish and emit the signal "result(QByteArray)" to trigger taskResult slot.
The first and second client will be trigger slot.
But the taskResult is not matter about second socket client. -
Hi,
You should map your tasks with the socket it shall report to. That way when the task is done you can retrieve the appropriate socket and then write the result to it.