QThread 和 QTcpSocket [关闭]

Posted

技术标签:

【中文标题】QThread 和 QTcpSocket [关闭]【英文标题】:QThread and QTcpSocket [closed] 【发布时间】:2013-01-08 07:14:44 【问题描述】:

我在做一些项目时犯了严重的错误,现在我必须从底部重新编程。我正在编写多线程服务器,它将处理连接、请求等。但是,当我创建新的具有 QThread 基对象的类,我使用 QThread->run() 启动线程,而不是 QThread->start()。现在我得到一堆错误。这里的情况。 我有服务器,它在每个连接上创建新线程并开始从每个连接的客户端读取数据。当我收到数据时,它会发出连接到主 GUI 类的信号并显示结果 OK。它还保存用于回复消息的套接字句柄。当我从 GUI 类向套接字写入数据时,它会这样说:

QObject:无法为不同线程中的父级创建子级。 (Parent是QNativeSocketEngine(0x23a6c38),parent的线程是MyThread(0x1fb8670),当前线程是QThread(0x9eb980)

怎么了?

【问题讨论】:

你不能用 run 方法启动线程。如果你使用 run 方法你没有启动线程,你只是在当前线程上下文中调用了常规方法。看看线程财富服务器doc.qt.digia.com/qt/network-threadedfortuneserver.html可能会有所帮助 如果您使用的是 Qt 4,那么很遗憾,QThread 文档具有误导性和过时性,并且应该在几年前进行更新。幸运的是,他们最终提供了 a much more accurate documentation 以及 Qt5,我强烈建议您阅读它,因为它也适用于 Qt 4。Kamil Klimek 链接的 threadedfortuneserver 示例已经遵循 Qt 5 指南。 然后我应该检查线程财富服务器以深入了解流程是如何工作的。这对我来说很难,但我会试一试。谢谢。 格式化您的问题。很难阅读 【参考方案1】:

我知道 QT,但对 QT 套接字实现本身并不熟悉,但是从您的错误消息的声音和您描述设计的方式来看,您的问题与 QT 无关,而是与线程/套接字架构有关一般来说。多线程应用程序需要经过深思熟虑的智能设计才能高效,并确保您的会话数据等是一致的,并且不会充满并发问题、孤立的数据结构等。

它还保存了用于回复消息的套接字句柄。当我从 GUI 类向套接字写入数据时,它会说...:

在不了解实现的所有细节的情况下,如果您将套接字句柄保留在线程 1 中以响应线程 1 中的调用,然后尝试使用线程 2 从调用向其写入数据,则原始套接字句柄为在线程 2 的上下文中无效。这可以解释您的错误消息。

由于各种原因(包括您遇到的问题),为后续调用保留套接字句柄并不是一个好方法。您为什么要这样做?如果您需要跨调用保留客户端信息,请使用会话结构来保留该数据。如果您想在来回对话继续时保持整个线程处于活动状态,请将您的线程/套接字交互设计为以这种方式运行并考虑线程池等。但是您不应该只是闲置孤立的套接字 - 每个都必须存在于它自己的线程上下文,并且在其“主”线程之外​​没有有效的句柄。

当一个套接字完成其对话时,产生的线程和在该线程中创建的用于继续对话的套接字都已完成 - 应该全部清理。

如果我正确理解您的实现,我的建议应该可以解决您的问题。

您在评论中提到:

“socket as a global variable”-如果我理解正确你在做什么,你不应该以这种方式使用全局套接字。 p>

您的服务器应用程序应该有一个带有持久套接字的主线程,用于侦听请求,当您收到请求时,应该发出一个信号,并且该信号的插槽应该产生一个线程,该线程初始化一个新的套接字以进行处理那个请求。在线程中处理请求,然后清理一切,等等。

如果您需要从传入的请求中提取信息并将其保存在某处,请在主线程中进行,其他线程不应访问您用于在主线程中为该会话保存的结构(除非您使用同步机制) 如果您想在请求处理完成后从请求处理中获取信息,同样的事情 - 通过线程终止时发出的信号将其从生成的线程中返回到主线程中。

如果您不遵守这些规则,则需要使用同步对象,否则您将遇到各种问题,包括您遇到的问题,从您的错误消息的声音来看。

简而言之:“线程中发生的事情,停留在线程中”

【讨论】:

嗨,主要问题是我是 Qt 新手,有时我什至不明白自己在做什么。现在想象下面的事情。我将 QTcpSocket *socket 作为全局变量,可以从任何类访问它,并且结果相同。当新连接到达时,socket = 新连接socket。当我试图将数据从另一个类写入这个套接字时,它只会给我这个错误。 "socket as a global variable" - 如果我理解正确你在做什么,你不应该以这种方式使用全局套接字。 您的服务器应用程序应该有一个带有持久套接字的主线程来侦听请求,当您收到请求时应该发出一个信号,并且该信号的插槽应该产生一个初始化线程用于处理该请求的新套接字。在线程中处理请求,然后清理一切,等等。 如果您需要从传入的请求中提取信息并将其保存在某处,请在主线程中进行,其他线程应该无法访问您用于在主线程中保存的结构。如果您想在请求处理完成后从请求处理中获取信息,同样的事情 - 通过线程终止时发出的信号将其从生成的线程中返回到主线程中。如果您不遵守这些规则,则需要使用同步对象,否则您将遇到各种问题,包括您遇到的问题,从错误消息的声音来看。 简而言之-我知道QT,但对QT套接字实现本身并不十分熟悉,但是从您的错误消息的声音和您描述设计的方式来看,您的问题与QT无关,而是一般来说,线程/套接字架构。 HTH

以上是关于QThread 和 QTcpSocket [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

QTcpSocket使用过程中的一些问题记录

QTcpSocket Disconnected() 未发出信号

QTcpSocket 或 QSslSocket 会自动创建读/写线程吗?

QT下QThread学习

QTcpSocket 客户端自动重连

无法关闭 QThread - 应用程序崩溃