0

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

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

怎么了?

4

1 回答 1

1

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

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

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

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

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

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

在您的评论中,您提到:

“套接字作为全局变量” -如果我正确理解你在做什么,你不应该以这种方式使用全局套接字。

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

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

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

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

于 2013-01-08T07:56:45.713 回答