Qt:Qt中的多线程技术
Qt提供了许多用于处理线程的类和函数。 Qt程序员可以使用以下四种不同的方法来实现多线程应用程序。
QThread:具有可选事件循环的低级API
QThread
是Qt中所有线程控制的基础。每个QThread实例代表并控制一个线程。
QThread可以直接实例化也可以子类化。实例化QThread提供了一个并行事件循环,从而允许在辅助线程中调用QObject槽。子类化QThread允许应用程序在开始其事件循环之前初始化新线程,或者在没有事件循环的情况下允许并行代码
有关如何使用QThread的演示,请参见QThread类参考和线程示例
QThreadPool和QRunnbale:重用线程
频繁创建和销毁线程可能会很昂贵。为了减少这种开销,可以将现有线程重用于新任务。QThreadPool是可重用的QThreads的集合。
要在QThreadPool的线程之一中运行代码,请重新实现QRunnable::run()并实例化子类QRunnable。使用QThreadPool :: start()将QRunnable放入QThreadPool的运行队列中。当线程可用时,QRunnable::run()中的代码将在该线程中执行。
每个Qt应用程序都有一个全局线程池,可通过QThreadPool::globalInstance()访问该线程池。该全局线程池根据CPU中的内核数自动维护最佳线程数。但是,可以显式创建和管理单独的QThreadPool。
Qt Concurrent:使用高级API
Qt并发模块提供了处理一些常见并行计算模式的高级函数:map、filter和reduce。与使用QThread和QRunnable不同,这些函数从来不需要使用低级线程原语,比如互斥锁或信号量。相反,它们返回一个QFuture对象,当函数准备好时,该对象可用于检索函数的结果。QFuture还可以用于查询计算进度和pause/resume/cancel计算。为了方便,QFutureWatcher允许通过信号和插槽与QFutures进行交互。
Qt Concurrent的map、filter和reduce算法会自动将计算分配到所有可用的处理器核上,因此今天编写的应用程序在以后部署到更多核的系统上时将继续扩展。
这个模块还提供了QtConcurrent::run()函数,它可以在另一个线程中运行任何函数。但是,QtConcurrent::run()只支持map、filter和reduce函数可用特性的子集。可以使用QFuture来检索函数的返回值,并检查线程是否正在运行。但是,调用QtConcurrent::run()只使用一个线程,不能暂停/恢复/取消,也不能查询进度。
有关单个函数的详细信息,请参阅Qt并发模块文档。
WorkerScript:QML中的线程
WorkerScript QML类型允许JavaScript代码与GUI线程并行运行。
每个WorkerScript实例可以附加一个.js脚本。调用WorkerScript.sendMessage()时,脚本将在单独的线程(和单独的QML上下文)中运行。脚本运行完毕后,可以将答复发送回GUI线程,该线程将调用WorkerScript.onMessage()信号处理程序。
使用WorkerScript类似于使用已经移到另一个线程的worker QObject。数据通过信号在线程之间传输。
有关如何实现脚本的详细信息以及可以在线程之间传递的数据类型的列表,请参见WorkerScript文档。
选择适当的方法
如上所述,Qt为开发多线程应用程序提供了不同的解决方案。给定应用程序的正确解决方案取决于新线程的目的和线程的生存期。下面是Qt线程技术的比较,然后是一些用例的推荐解决方案。
解决方案对比
使用示例
还没有评论,来说两句吧...