【发布时间】: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
标签: qt qthread qtconcurrent