如何在不同的线程中执行 QTcpSocket?
如何在不同的线程中执行 QTcpSocket 函数?
How do I execute QTcpSocket functions in a different thread?
推荐答案
重要的是要注意在线程方面你能做什么和不能做什么QTcpSocket
:
It's important to note what you can and can't do in terms of threading QTcpSocket
:
您可以在非主线程中使用它,但只能在创建它的线程中使用.
you can use it in a non-main thread, but only the thread in which it was created in.
你不能从不同的线程调用 QTcpSocket
上的不同函数,例如在一个线程中读取,在另一个线程中写入.相反,您可以为每个 QTcpSocket
创建一个单独的线程,这样它们就不会占用可能在主线程中绘制小部件的时间和资源.
you cannot call different functions on the QTcpSocket
from different threads, e.g. read in one thread, write in the other. Instead, you can make a seperate thread for each QTcpSocket
, which keeps them from using up time and resources that could be painting your widgets in the main thread.
IMO,将您的 IO,包括 QTcpSocket
放在主线程以外的线程中是最佳实践,并且对于任何高性能应用程序来说都是必须的.我一直在非主线程中使用 QTcpSocket
使用以下习惯用法:
IMO, putting your IO, including QTcpSocket
in a thread other than the main thread is a best practice and must-do for any performant application. I use QTcpSocket
in non-main threads all the time using the following idiom:
// 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
具有互斥保护的容器.
where m_thread
is some member thread (basically just ensuring that it has a lifetime greater than the current immediate scope), and m_concurrentQueue
is some thread-safe queue, or std
container with mutex protection.
您还需要将一些信号(我通常称之为 joinAll
)连接到事件循环退出函数,并从类析构函数中调用它.当使用事件循环在线程中的习惯用法时,你总是要小心确保你可以正确地销毁类,否则你的程序不会退出(或者在 Windows 上它会被终止,通常带有一些析构函数没有被调用,它最终是一个无声的错误).
You'll also want to connect some signal (I usually call it joinAll
) to the event loop quit function, and call it from the class destructor. When using an event-loop-in-a-thread idiom you always have to be careful about making sure you can actually destroy the class correctly, otherwise your program won't exit (or on windows it will be terminated, usually with some destructors not getting called, and it ends up being a silent error).
我通常也使用条件变量在创建线程后等待事件循环开始.这不是必需的,但如果您将这些线程放在构造函数中,它可以帮助使程序流更有意义.
I also usually use a condition variable to wait after creating the thread until the event loop has started. It's not necessary but if you are putting these threads together in constructors it can help make the program flow make more sense.
相关文章