首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >QThread与std::线程

QThread与std::线程
EN

Stack Overflow用户
提问于 2016-10-27 12:40:51
回答 3查看 15.1K关注 0票数 15

我看到了不同的主题:“p线程对std::QThread”和"QThread vs“,但是在”std::topics“上没有一个主题。

我必须编写一个软件来驱动3D打印机,并需要使用线程。将有一个线程将不断检查安全性,另一个线程执行打印过程,一些线程用于驱动每个硬件组件(移动、喷射、.)分开等等..。该程序是在Windows环境下用C++11/Qt开发的。

首先,我想使用QThread,但在我看来,QThread不允许您执行与std::一样多的事情,例如,在阅读Anthony Williams的"C++并发操作“时,我发现可以要求std::线程通过执行类似于QThread似乎不可能的操作从另一个线程执行函数。

--我最想要的机制是,如果我希望在当前线程或另一个线程中执行一个函数,可以这样说。

你会选择哪一个去做,为什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-10-27 13:23:28

QThread不仅仅是一个线程,它还是一个线程管理器。如果你想让你的线程玩Qt,那么QThread就是最好的选择。Qt是事件驱动的,大多数现代编程也是如此。这比“让线程运行函数”要复杂和灵活一些。

在Qt中,您通常会与QThread一起创建一个工作者,将工作人员移动到该线程,然后由事件系统为该工作者对象调用的每个函数都将在与worker对象有关联的线程中执行。

因此,您可以将您的功能封装在不同的worker对象中,例如SafetyCheckerPrinterServoDriverJetDriver等等,创建每个工作对象的实例,将其移动到一个专用线程,然后设置。您仍然可以调用将“阻塞”而不是使用细粒度事件的函数,还可以使用atomics或互斥来执行线程间同步。只要不阻塞主/gui线程,这没有什么问题。

您可能不希望执行由打印机代码驱动的事件,因为在多线程场景中,需要排队的连接比直接连接甚至虚拟调度稍微慢一些。因此,如果您的多线程粒度太细,您可能实际上会遇到巨大的性能问题。

尽管如此,使用Qt的非gui工具有其自身的优点,它将使您的设计变得更干净、更灵活,而且如果实现得当,您仍然可以获得多线程的好处。您仍然可以使用事件驱动的方法来管理整个事件,这将比仅使用std::thread要容易得多,这是一个低得多的级别结构。您可以使用事件驱动的方法来设置、配置、监视和管理设计,而关键部分可以在辅助线程中的阻塞函数中执行,以便在尽可能低的同步开销下实现细粒度控制。

为了澄清--答案并不集中在异步任务的执行上,因为其他两个答案已经解决了,而且正如我在注释中提到的那样,异步任务并不真正用于控制应用程序。它们适合于执行小任务,这些任务仍然比您希望阻塞主线程所花费的时间更长。作为一个推荐的指导方针,任何花费超过25毫秒的东西都比执行异步更好。而打印可能需要几分钟或甚至几个小时,并意味着连续运行控制功能,并行和使用同步。异步任务不会为控制应用程序提供性能、延迟和顺序保证。

票数 18
EN

Stack Overflow用户

发布于 2016-10-27 13:25:04

std::threadQThread的主要问题是它做了它在tin上说的事情:为您创建一个线程,这个线程很可能只做一件事情。使用std::thread“并发”运行一个函数是非常浪费的:线程是昂贵的资源,因此只为运行某个函数创建一个线程通常是多余的。

虽然std::thread t1(&Class::function, this, ...)看起来不错,但这通常是一种过早的悲观,并认为它是某种“同时做事”的普遍方式是错误的。你可以做得更好。

  1. 如果要在工作线程中并发运行函数/函子/方法,请使用QtConcurrent::run std::async**.**或 默认情况下,QtConcurrent::run使用默认线程池,您也可以传递自己的QThreadPool实例。一个典型的例子是将默认线程池用于CPU绑定的任务,例如计算、图像转换、呈现等,并使用一个专用的、较大的I/O线程池来执行由于您被迫使用的API的限制而阻塞的操作(例如,许多数据库库只提供阻塞API,因为它们的设计根本上是错误的)。示例: // QThreadPool * ioPool();//实现Q_GLOBAL_STATIC( QThreadPool,ioPool_impl);QThreadPool* ioPool() {返回ioPool_impl;}
  2. 如果您希望在另一个线程中运行一个QObject QThread (可能与其他对象共同居住),请使用QThread,然后使用 moveToThread**.**将对象移动到该线程。 它是一个成语,从工作线程发出信号到线程--安全地将数据传递到主线程。例如,假设您希望具有响应性GUI,并希望在工作线程中从磁盘加载映像: MyWidget类: public QWidget { QLabel m_label;.Q_SIGNAL void setImage(const QImage &);public: MyWidget() {…连接(MyWidget,&MyWidget::setImage,this,{ m_label.setPixmap(QPixmap::fromImage(image));});QtConcurrent::run(ioPool(),this{ setImage({"/path/to/image.png"});};
票数 8
EN

Stack Overflow用户

发布于 2016-10-27 12:56:48

如果您想将线程集成到Qt系统中(比如必须发出信号或连接到特定的插槽),那么QThread是很好的。

尽管QThread的布局仍然是制作的,所以它与“旧”c++一起工作。您必须创建一个类,所有这些开销(代码和输入wise)只是为了在线程中运行。

如果您只是想启动一个线程,我认为c++11 std::thread不那么冗长/您必须编写的代码。您只需使用lambda或函数指针,就可以提供任意数量的参数。因此,对于简单的线程处理,我建议在QThreads上使用QThreads线程。

当然,这可以是一个意见的问题,谁是你喜欢。

虽然Qt有几个不同的高级线程对象,但C++没有。如果您需要一些基本线程而不是基本线程,那么您可能需要查看这些线程,或者您可能根本不需要基本线程,但它们更适合您。

就像一个QThreadPool或者简单的QTimer,如果你需要等待的话。这里是一些关于Qt中裸线程的替代品的读物。

例如,QConcurrent更接近于c++11、futureasync,并且还有可选的线程池,可以在其中运行。

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

https://stackoverflow.com/questions/40284850

复制
相关文章

相似问题

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