无法写入 QRunnable 内的 QTcpSocket
Posted
技术标签:
【中文标题】无法写入 QRunnable 内的 QTcpSocket【英文标题】:Can not write to QTcpSocket inside QRunnable 【发布时间】:2018-01-18 21:34:33 【问题描述】:我在Qt
中构建了一个服务器,它接收每个连接到它的客户端并将连接发送到工作线程(我用QRunnable
实现了这一点,并将线程连接到QThreadPool
)。
在我的线程中,我从套接字 (QTcpSocket socket
) 读取没有问题,但是当我尝试写入它时,我收到以下错误:
QObject:不能为不同的父级创建子级 线。父线程是QThread(0x28602f90860)
我尝试通过添加代码行来解决此问题:
socket->setParent(this);
在我的线程的构造函数中 - 但它没有帮助,我收到以下错误:
QObject:无法为不同线程中的父级创建子级。 (Parent是QNativeSocketEngine(0x1dab6331c60),parent的线程 是 QThread(0x1dab62eacf0),当前线程是 QThread(0x1dab632b140) QSocketNotifier:不能启用或禁用套接字通知 另一个线程
有谁知道这是什么问题或如何解决?
相关代码sn-ps的稀疏示例:
class myTask : public QObject , public QRunnable, public parser
Q_OBJECT
public:
myTask(QTcpSocket *s)
socket = s;
socket->setParent(this);
// if i do here socket->write("hello world"); it's work , but not in run()
signals:
void Result(int num);
protected:
void run()
socket->write("hello world"); // i get here the error
private:
QTcpSocket *socket;
;
/* the creation of the worknig thread and the tcp client creation */
void MyClient::readyRead()
myTask * mtask = new myTask(socket);
mtask->setAutoDelete(true);
// connect result to our loacal result function
connect(mtask, SIGNAL(Result(int)), this, SLOT(taskResults(int)), Qt::QueuedConnection);
//start havy job
QThreadPool::globalInstance()->start(mtask);
void MyClient::SetSocket(int descriptor)
socket = new QTcpSocket(this);
connect(socket, SIGNAL(connected()), this, SLOT(connected()));
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
socket->setSocketDescriptor(descriptor);
qDebug() <<"[*] client connected";
class MyClient : public QObject
Q_OBJECT
public:
explicit MyClient(QObject *parent = nullptr);
void SetSocket(int descriptor);
signals:
public slots:
void connected();
void disconnected();
void readyRead();
void taskResults(int num);
private:
QTcpSocket *socket;
;
【问题讨论】:
当然,问题可能与其他问题有关,而不是 QRunnable,它只是关于产生非阻塞任务。当然,您可以在没有“任务”的情况下以非阻塞方式使用 QTcpSocket。我会从这个开始,去掉不必要的细节的例子通常会有所帮助。如果可行,那么问题出在 QRunnable 使用的方式 而 not 与套接字有关。 如果你尝试从myTak constructor
发送它工作正常,只有从迷你我进入run()
我开始得到错误
什么是“繁重的工作”?作为@AlexanderVX,Qt 的网络模块是异步的,设计用于主线程,因此您不需要将任何网络 I/O 本身移动到另一个线程。此外,您不能将对象移动到其父对象不存在的线程中,也不应从套接字不存在的线程中调用套接字的 read()
或 write()
函数。
heavy job
是从网络文件中获取的,对此进行一些操作并将它们写回客户端,我在单独的可运行中执行它,因为我想要一个真正的多线程并避免任何阻塞行为 -它应该是功能齐全的真实服务器。
@YOKO 我建议您首先阅读有关线程和 QObject 的 Qt 文档。这将帮助您了解在跨线程使用 QObject 时可以做什么和不可以做什么:doc.qt.io/qt-5/threads-qobject.html
【参考方案1】:
如果您查看 QTcpServer
文档,其中一条注释说:
注意:如果您想在另一个线程中将传入连接作为新的
QTcpSocket
对象处理,您必须将socketDescriptor
传递给另一个线程并在那里创建QTcpSocket
对象并使用其setSocketDescriptor()
方法。
为此,incomingConnection()
上还有一条注释:
注意:返回的
QTcpSocket
对象不能被其他线程使用。如果你想使用来自另一个线程的传入连接,你需要overrideincomingConnection()
。
所以子类QTcpServer
类并实现一个incomingConnection()
获取套接字描述符 并发送到线程。
这里是线程QTcpServer
的example。
【讨论】:
以上是关于无法写入 QRunnable 内的 QTcpSocket的主要内容,如果未能解决你的问题,请参考以下文章