在上一个问题中,我没有清楚地表达我的用例。现在我描述我的要求。 在我的客户端,我需要使用QTcpSocket连接到服务器。在大多数情况下,我可以在gui线程(主线程)中编写和读取。 但是,在一些耗时的任务中,我需要一个工作线程来执行任务。当我用gui线程连接服务器时,我一直保持连接。 如果我在工作线程中使用新的QTcpSocket,我必须断开gui线程中的套接字吗?并再次连接到服务器?
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;
}
答案 0 :(得分:0)
解决问题的简单方法是不直接从工作线程访问QTcpSocket。最终,您可能想要使用来自工作线程的套接字来向它发送和/或接收数据。在这种情况下,您可以让工作线程发出带有QByteArray参数的信号,然后将该信号连接到GUI线程上的插槽,然后在QTcpSocket上调用write(const QByteArray& byteArray)
。类似地,您可以使用数据接收函数(无论连接到套接字的readyRead()信号)是存在于工作线程中,还是存在于主线程中,但是在收到工作线程需要处理的数据时,通过信号/插槽连接传递数据。
另一种选择,如果你必须直接访问套接字(比如,你需要做的不仅仅是写入它,也许你必须能够关闭它或其他什么),你需要将每个套接字的使用包装在一个套接字中。 mutex,在两个线程上。这可能是最好的方法是将原始QTcpSocket包装在另一个只暴露你需要的几个方法的类中,并且总是有一个调用:
QMutexLocker locker(theMutex);
在每个函数的开头。
答案 1 :(得分:-2)
有没有理由你不能将套接字传递给线程的构造函数?
class Worker : public QThread{
public:
Worker(QTcpSocket* pSocket) : m_pSocket(pSocket) ...
不确定您的使用案例,但是有理由不能这样做吗?
来自文档:http://doc.qt.io/qt-4.8/qiodevice.html
QIODevice的某些子类,例如QTcpSocket和QProcess,是异步的。这意味着诸如write()或read()之类的I / O函数总是立即返回,而当控制返回到事件循环时,可能会发生与设备本身的通信。 QIODevice提供的功能允许您强制立即执行这些操作,同时阻止调用线程并且不进入事件循环。这允许在没有事件循环的情况下使用QIODevice子类,或者在单独的线程中使用: