如何在不同的线程中执行QTcpSocket函数?
答案 0 :(得分:6)
QT文档明确指出QTCPSocket不应该在线程中使用。 I.E,在主线程中创建一个QTCPSocket,并将信号绑定到另一个线程中的对象。
我怀疑你正在实现类似于web服务器的东西,其中listen在accept上创建了一个QTCPSocket。然后,您需要另一个线程来处理处理该套接字的任务。你不能。
我解决这个问题的方法是将套接字保留在它所生成的线程中。我为该线程中的所有传入数据提供服务并将其放入队列中,其他线程可以处理该数据。
答案 1 :(得分:5)
请务必注意在线程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;
});
其中m_thread
是某个成员线程(基本上只是确保其生存期大于当前立即作用域),而m_concurrentQueue
是某个线程安全队列或std
容器具有互斥保护。
您还需要将一些信号(通常称为joinAll
)连接到事件循环退出函数,并从类析构函数中进行调用。当使用线程中的事件循环习惯时,您始终必须注意确保可以正确地销毁该类,否则您的程序将不会退出(或在Windows上通常会被某些析构函数终止)不会被调用,并且最终会变成一个无提示错误)。
我通常也使用条件变量在创建线程之后等待事件循环开始。不必要,但是如果将这些线程放到构造函数中,则可以帮助使程序流程更有意义。
答案 2 :(得分:1)
围绕所有调用设置QMutex
锁定,而不仅仅是在“不同”线程上,而是在所有线程上。一种简单的方法是通过QMutexLocker
答案 3 :(得分:1)
我在文档中读到的是QTcpSocket不应跨线程使用。如果你想在另一个线程中使用它,Qt docs说你应该在线程中创建一个新的QTcpSocket实例,并在新实例上设置描述符。为此,您需要重新实现QTcpServer并使用QTcpServer::incomingConnection。提供了一个简单示例here。
答案 4 :(得分:-4)
以下是示例:
file thread.h:
class Thread : public QThread {
Q_OBJECT
public:
Thread();
protected:
void run();
}
file thread.cpp:
Thread::Thread() {}
void Thread::run() {
// do what ever you want with QTcpSocket
}
在main.cpp或其他:
Thread *myThread = new Thread;
connect(myThread, SIGNAL(finished()), this, SLOT(on_myThread_finished()));
myThread->start();