简体   繁体   中英

how to use QTcpSocket in multithread?

in last question,i don't express my use-case clearly. now i describe my requirement. in my client,i need to connect to Server with QTcpSocket.in most cases, i can write and read in gui thread(main thread). how ever,in some time-consuming tasks,i need a single worker thread to execute task. when i connect the server in gui thread,i keep the connection all the time. if i use a new QTcpSocket in worker thread,must i disconnect the socket in gui thread? and connect to Server again?

class Widget:public QWidget
{
    Q_OBJECT
public:
    Widget()
    {
        socket = new QTcpSocket(this);
    }   
private:
    QHostAddress host;
    unsigned int port;
    QTcpSocket *socket;
private slots:  
    void startConnect()
    {
        socket->connectToHost(host,port);
    }
    void sendData()
    {
        //just send some bytes
        //socket->write();
    }
    void doTimeConsumingTask()
    {
        //must i disconnect gui->socket connection before the Worker is running?
        // socket->disconnectFromHost();
        Worker * w = new Worker();
        w->start();
    }
}

class Worker:public QThread
{
    Q_OBJECT
public:
    Worker()
    {

    }
protected:
    void run()
    {
        QTcpSocket socket;
        // must i connectToHost again here ? 


        // do something consuming time
        while(true){
            //
            QThread::msleep(10);

        }
    }
private:
    QHostAddress host;
    unsigned int port;
}

The easy solution to your problem is to not directly access the QTcpSocket from the worker thread. Ultimately, all you probably want to do with the socket from the worker thread is send and/or receive data to/from it. In that case, you can simply have the worker thread emit a signal with a QByteArray parameter, then connect that signal to a slot on the GUI thread that then calls write(const QByteArray& byteArray) on the QTcpSocket. Similarly, you can have your data receive function (whatever is connected to the readyRead() signal of the socket) either live in the worker thread, or live in your main thread, but upon receipt of data that the worker thread needs to process, pass it that data via a signal/slot connection.

The alternative, if you must directly access the socket (say, you need to do more than write to it, maybe you have to be able to close it or whatever), you need to wrap every use of that socket in a mutex, on both threads. This is probably best done by wrapping the raw QTcpSocket in another class that exposes only a few methods that you need, and always has a call like: QMutexLocker locker(theMutex); At the beginning of each function.

Is there a reason you can't pass the socket to the thread's constructor?

class Worker : public QThread{
public:
    Worker(QTcpSocket* pSocket) : m_pSocket(pSocket) ...

Not sure of your use case but is there a reason you can't do this?

From the docs: http://doc.qt.io/qt-4.8/qiodevice.html

Certain subclasses of QIODevice, such as QTcpSocket and QProcess, are asynchronous. This means that I/O functions such as write() or read() always return immediately, while communication with the device itself may happen when control goes back to the event loop. QIODevice provides functions that allow you to force these operations to be performed immediately, while blocking the calling thread and without entering the event loop. This allows QIODevice subclasses to be used without an event loop, or in a separate thread:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM