QThread vs std :: thread

时间:2016-10-27 12:40:51

标签: c++ multithreading qt std qthread

我在“pthread vs std :: thread”和“QThread vs pthread”上看到了不同的主题,但在“std :: thread vs QThread”上没有看到。

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

首先我想使用QThread,但在我看来,QThread不允许你像std :: thread 那样做很多事情,例如,在阅读“C ++ Concurrency in Action”时作者:Anthony Williams,我看到有可能让std :: thread通过做std::thread t1(&Class::function, this, ...);这样的事情从另一个线程执行一个函数,而QThread似乎无法做到这一点。

我想拥有的机制是一种说法,如果我想在当前线程或另一个线程中执行函数。

您会选择哪一个以及为什么?

3 个答案:

答案 0 :(得分:13)

QThread不仅仅是一个线程,它也是一个线程管理器。如果你想让你的线程玩Qt,那么QThread就是你要走的路。 Qt是事件驱动的,就像大多数现代编程一样。这比#34;使线程运行一个功能更加复杂和灵活。

在Qt中,您通常与QThread一起创建一个worker,将worker移动到该线程,然后事件系统为该worker对象调用的每个函数都将在该线程中执行worker对象具有亲和力。

因此,您可以将功能封装在不同的工作对象中,比如SafetyCheckerPrinterServoDriverJetDriver等,创建每个工具对象,移动它到一个专门的线程,你已经设置好了。您仍然可以调用阻止"阻止"而不是使用细粒度事件,并使用原子或互斥体来进行线程间同步。这没有什么不妥,只要你不阻止主/ gui线程。

您可能不希望执行打印机代码事件驱动,因为在多线程方案中涉及排队连接,这比直接连接甚至虚拟分派慢一点。这么多,如果你让你的多线程太精细,你实际上可能会遇到巨大的性能损失。

话虽如此,使用Qt的非gui东西有其自身的优点,它将使您更容易制作更清晰,更灵活的设计,如果您实现的话,您仍将获得多线程的好处正常。您仍然可以使用事件驱动的方法来管理整个事情,它比仅使用std::thread要容易得多,public function install() { return parent::install() && your hook registers && $this->updateHookPosition('displayTopColumn', 0 /* DESC */, 1); } public function updateHookPosition($hook_name, $way, $position) { $id_hook = Hook::getIdByName($hook_name); return $this->updatePosition($id_hook, $way, $position); } 是一个更低级别的构造。您可以使用事件驱动的方法来设置,配置,监视和管理设计,而关键部分可以在辅助线程中的阻塞功能中执行,以尽可能低的同步开销实现细粒度控制。

澄清一下 - 答案并不专注于异步任务执行,因为其他两个答案已经完成,因为正如我在评论中提到的,异步任务并不是真正用于控制应用程序。它们适合执行小任务,这些任务仍然需要比你想要阻止主线程更多的时间。作为推荐的指导原则,超过25毫秒的所有内容最好不要执行异步。而打印可能需要几分钟甚至几小时,并且意味着连续运行控制功能,并行和使用同步。异步任务不会为您提供控制应用程序的性能,延迟和顺序保证。

答案 1 :(得分:7)

std::threadQThread的主要问题在于它在锡上执行的操作:为您创建一个线程,一个可能只做一件事的线程。同时运行一个功能"使用std::thread是非常浪费的:线程是昂贵的资源,所以创建一个只是为了运行某些功能通常是矫枉过正。

虽然std::thread t1(&Class::function, this, ...)看起来不错,但通常是过早的悲观,并建议将其视为同时做事的一种普遍方式。是恕我直言错了。你可以做得更好。

  1. 如果要在工作线程中同时运行函数/仿函数/方法,请使用QtConcurrent::runstd::async

    QtConcurrent::run默认使用默认线程池,您也可以传递自己的QThreadPool实例。典型的情况是将默认线程池用于CPU绑定任务,例如计算,图像转换,渲染等,并使用专用的,更大的I / O线程池来执行由于您强制使用的API的限制而阻塞的操作(例如,许多数据库库仅提供阻塞API因为他们的设计从根本上被打破了。例如:

    // interface
    QThreadPool * ioPool();
    
    // implementation
    Q_GLOBAL_STATIC(QThreadPool, ioPool_impl);
    QThreadPool * ioPool() { return ioPool_impl; }
    
  2. 如果你想让QObject在另一个线程中生活(可能与其他对象共存),请使用QThread然后使用{{}将对象移动到该线程1}}

    从工作线程发出信号以将数据线程安全地传递给主线程是一种习惯用法。例如。假设您希望拥有一个响应式GUI并希望在工作线程中从磁盘加载图像:

    moveToThread

答案 2 :(得分:6)

QThread很好,如果你想将线程集成到Qt系统中(比如必须发出信号或连接到某些插槽)

虽然仍然制作QThread的布局,但它适用于" old" C ++。你必须创建一个类,所有这些开销(代码和打字明智)只是为了在一个线程中运行。

如果你只想创建一个线程,我认为c ++ 11 std::thread不那么详细/代码你必须写。您可以使用lambda或函数指针,并可以根据需要提供尽可能多的参数。因此,对于简单的线程,我建议在QThreads上使用c ++ 11线程。

当然,你最喜欢的是哪个意见问题。

虽然Qt有几个不同的高级线程对象,但C ++却没有。你可能想要研究这些,如果你需要其中一些而不是一个基本的线程,或者你根本不需要一个基本的线程,但那些更适合你。

如果您需要等待事情,请像QThreadPool或简单地QTimerHere是关于Qt中替代方案的一些读法。

QConcurrent也更接近于c ++ 11 futureasync,并且还有可运行的可选线程池。