如何在不同的线程中执行QTcpSocket?

Reg*_*gof 6 c++ qt multithreading tcp qt4

如何在不同的线程中执行QTcpSocket函数?

小智 6

QT文档明确指出QTCPSocket不应该在线程中使用.IE,在主线程中创建一个QTCPSocket,并将信号绑定到另一个线程中的对象.

我怀疑你正在实现类似于web服务器的东西,其中listen在accept上创建了一个QTCPSocket.然后,您需要另一个线程来处理处理该套接字的任务.你不能.

我解决这个问题的方法是将套接字保留在它生成的线程中.我为该线程中的所有传入数据提供服务并将其放入一个队列,其中另一个线程可以处理该数据.


Nic*_*aus 6

重要的是要注意在线程方面您可以做什么和不能做什么QTcpSocket

  • 可以在非主线程中使用它,但只能在创建它的线程中使用。

  • 不能QTcpSocket从不同的线程调用不同的函数,例如在一个线程中读取,在另一个线程中写入。相反,您可以为每个 制作一个单独的线程QTcpSocket,这样可以防止它们占用可能在主线程中绘制小部件的时间和资源。

IMO,将您的 IO,包括QTcpSocket在主线程以外的线程中,是任何高性能应用程序的最佳实践和必须做的事情。我一直使用QTcpSocket以下习语在非主线程中使用:


// Read data from a QTcpSocket in a thread. Assumes this is in some class.
m_thread = std::thread([this]
{
    QEventLoop eventLoop;
    QTcpSocket* socket = new QTcpSocket(&eventLoop);

    socket->connectToHost("localhost", 9999);

    // enqueue or process the data
    QObject::connect(socket, &QTcpSocket::readyRead, &eventLoop, [socket]
    {

        m_concurrentQueue.push_back(socket->readAll());
    });

    // Quit the loop (and thread) if the socket it disconnected. You could also try
    // reconnecting
    QObject::connect(socket, &QTcpSocket::disconnected, &eventLoop, [&eventLoop]
    {
        eventLoop.quit();
    });

    eventLoop.exec();

    delete socket;
});
Run Code Online (Sandbox Code Playgroud)

哪里m_thread是某个成员线程(基本上只是确保它的生命周期大于当前的直接范围),并且m_concurrentQueue是某个线程安全队列或std具有互斥保护的容器。

您还需要将一些信号(我通常称之为joinAll)连接到事件循环退出函数,并从类析构函数中调用它。当使用一个线程中的事件循环习语时,你总是要小心确保你可以正确地销毁类,否则你的程序不会退出(或者在 Windows 上它会被终止,通常带有一些析构函数没有被调用,它最终是一个无声的错误)。

我通常还使用条件变量在创建线程后等待事件循环开始。这不是必需的,但如果您将这些线程放在构造函数中,它可以帮助使程序流程更有意义。


MSa*_*ers 1

对所有调用加锁QMutex,不仅在“不同”线程上,而且在所有线程上。一种简单的方法是通过QMutexLocker