发布
社区首页 >问答首页 >如何在使用QThreadPool时执行QObject::moveToThread()?

如何在使用QThreadPool时执行QObject::moveToThread()?
EN

Stack Overflow用户
提问于 2010-06-27 02:12:48
回答 3查看 9.4K关注 0票数 7

我正在构建一个小型多线程web服务器。QTcpSockets是在主线程中获取的,然后由QtConcurrent交给QThreadPool,QThreadPool最终处理数据并发送一个答案。

我的问题是,套接字是在主线程中创建并在另一个线程中处理的。当试图写入套接字时,这会导致错误:

代码语言:javascript
代码运行次数:0
复制
socket->write(somedata);

QObject:不能为处于不同线程中的父线程创建子线程。(父线程为QNativeSocketEngine(0x608330),父线程为QThread(0x600630),当前线程为QThread(0x505f60) )。

干净的方法是将套接字对象移动到处理线程,使用

代码语言:javascript
代码运行次数:0
复制
socket->moveToThread(QThread::currentThread()).

但是,这只能在创建对象的线程中调用。此外,套接字将QTcpServer对象作为父对象,因此moveToThread()无论如何都会失败(父对象不能切换线程)。

如何将对象移动到线程池运行的代码中的QThread::currentThread()?或者,如何将其写入所创建线程外部的套接字?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-07-16 17:42:45

扩展QTcpServer,重新实现incomingConnection(int socketDescriptor),并将套接字描述符传递给池中的线程。让QRunnable从描述符创建QTcpSocket并启动事件循环来接收套接字的信号。

票数 4
EN

Stack Overflow用户

发布于 2015-01-02 00:09:24

我也同意,捕获incomingConnection(int)并在工作线程中创建套接字是这里的方法。

但是,您的问题是一个更基本的问题,因此请允许我展示一个解决一般问题的备选方案(将任意QObject移动到线程池中的线程):

主线程中的

  1. :将套接字与任何线程分离:

socket->moveToThread(nullptr);

这将挂起套接字的事件处理。然后将它传递给QtConcurrent.

  • In在线程池上执行的函数,现在可以调用

socket->moveToThread(QThread::currentThread());

这将重新启动事件处理.

如果幸运的话,套接字将使它的套接字通知器再次在辅助线程的事件循环中重新注册,并且您可以从工作器提供连接。

不过,这里有两个重要的警告

  • 您不应该将阻塞任务放在全局线程池(QThreadPool::globalInstance())上。正如函数的名称所示,线程池实例是一个全局资源,所有QtConcurrent用户都共享它,最好情况下阻塞它的工作线程会降低池的容量(因此,吞吐量),在最坏的情况下,您将使用工作线程的事件循环(由于第一点而不使用QTcpSocket的同步API ),您需要调用QThread::currentThread()->exec()来启动它。但是,这是一个阻塞调用,并且对线程池调度程序来说,工作人员看起来很忙,所以它不会交给它更多的任务(即。QRunnables).

如果您实际上想要实现多线程tcp服务器,那么您就需要提交自己的线程池。

票数 1
EN

Stack Overflow用户

发布于 2010-06-27 07:04:03

布拉德利·胡格在Qt实验室上写了一篇关于这个话题的文章,也许这会对你有所帮助!

https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3126145

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档