我看到了不同的主题:“p线程对std::QThread”和"QThread vs“,但是在”std::topics“上没有一个主题。
我必须编写一个软件来驱动3D打印机,并需要使用线程。将有一个线程将不断检查安全性,另一个线程执行打印过程,一些线程用于驱动每个硬件组件(移动、喷射、.)分开等等..。该程序是在Windows环境下用C++11/Qt开发的。
首先,我想使用QThread,但在我看来,QThread不允许您执行与std::一样多的事情,例如,在阅读Anthony Williams的"C++并发操作“时,我发现可以要求std::线程通过执行类似于QThread似乎不可能的操作从另一个线程执行函数。
--我最想要的机制是,如果我希望在当前线程或另一个线程中执行一个函数,可以这样说。
你会选择哪一个去做,为什么?
发布于 2016-10-27 13:23:28
QThread
不仅仅是一个线程,它还是一个线程管理器。如果你想让你的线程玩Qt,那么QThread
就是最好的选择。Qt是事件驱动的,大多数现代编程也是如此。这比“让线程运行函数”要复杂和灵活一些。
在Qt中,您通常会与QThread
一起创建一个工作者,将工作人员移动到该线程,然后由事件系统为该工作者对象调用的每个函数都将在与worker对象有关联的线程中执行。
因此,您可以将您的功能封装在不同的worker对象中,例如SafetyChecker
、Printer
、ServoDriver
、JetDriver
等等,创建每个工作对象的实例,将其移动到一个专用线程,然后设置。您仍然可以调用将“阻塞”而不是使用细粒度事件的函数,还可以使用atomics或互斥来执行线程间同步。只要不阻塞主/gui线程,这没有什么问题。
您可能不希望执行由打印机代码驱动的事件,因为在多线程场景中,需要排队的连接比直接连接甚至虚拟调度稍微慢一些。因此,如果您的多线程粒度太细,您可能实际上会遇到巨大的性能问题。
尽管如此,使用Qt的非gui工具有其自身的优点,它将使您的设计变得更干净、更灵活,而且如果实现得当,您仍然可以获得多线程的好处。您仍然可以使用事件驱动的方法来管理整个事件,这将比仅使用std::thread
要容易得多,这是一个低得多的级别结构。您可以使用事件驱动的方法来设置、配置、监视和管理设计,而关键部分可以在辅助线程中的阻塞函数中执行,以便在尽可能低的同步开销下实现细粒度控制。
为了澄清--答案并不集中在异步任务的执行上,因为其他两个答案已经解决了,而且正如我在注释中提到的那样,异步任务并不真正用于控制应用程序。它们适合于执行小任务,这些任务仍然比您希望阻塞主线程所花费的时间更长。作为一个推荐的指导方针,任何花费超过25毫秒的东西都比执行异步更好。而打印可能需要几分钟或甚至几个小时,并意味着连续运行控制功能,并行和使用同步。异步任务不会为控制应用程序提供性能、延迟和顺序保证。
发布于 2016-10-27 13:25:04
std::thread
和QThread
的主要问题是它做了它在tin上说的事情:为您创建一个线程,这个线程很可能只做一件事情。使用std::thread
“并发”运行一个函数是非常浪费的:线程是昂贵的资源,因此只为运行某个函数创建一个线程通常是多余的。
虽然std::thread t1(&Class::function, this, ...)
看起来不错,但这通常是一种过早的悲观,并认为它是某种“同时做事”的普遍方式是错误的。你可以做得更好。
QtConcurrent::run
std::async
**.**或
默认情况下,QtConcurrent::run
使用默认线程池,您也可以传递自己的QThreadPool
实例。一个典型的例子是将默认线程池用于CPU绑定的任务,例如计算、图像转换、呈现等,并使用一个专用的、较大的I/O线程池来执行由于您被迫使用的API的限制而阻塞的操作(例如,许多数据库库只提供阻塞API,因为它们的设计根本上是错误的)。示例:
// QThreadPool * ioPool();//实现Q_GLOBAL_STATIC( QThreadPool,ioPool_impl);QThreadPool* ioPool() {返回ioPool_impl;}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"});};发布于 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、future
和async
,并且还有可选的线程池,可以在其中运行。
https://stackoverflow.com/questions/40284850
复制相似问题