< p > < code >std::thread 和
QThread
的主要问题是,它们实现了字面意思:为您创建一个线程,这个线程可能只会做一件事情。使用
std::thread
并发运行函数非常浪费资源,因为线程是昂贵的资源,所以仅为运行某个函数而创建一个线程通常是过度kill的。
std::thread t1(&Class::function, this, ...)
看起来很不错,但通常是过早地进行优化,并将其作为“同时执行任务”的通用方法进行推荐不太妥当。有更好的方式。
< ol >
如果要在工作线程中同时运行函数/函数对象/方法,请使用QtConcurrent::run
或std::async
。
QtConcurrent::run
默认使用默认线程池,您也可以传递自己的QThreadPool
实例。典型情况下,将默认线程池用于CPU密集型任务,例如计算、图像转换、渲染等,并使用专用的更大的I/O线程池来执行由于API限制而阻塞的操作(例如,许多数据库库只提供阻塞API,因为它们的设计本质上是有缺陷的)。例如:
// interface
QThreadPool * ioPool();
// implementation
Q_GLOBAL_STATIC(QThreadPool, ioPool_impl);
QThreadPool * ioPool() { return ioPool_impl; }
如果您想让一个 QObject
存活在另一个线程中(可能与其他对象共存),请使用 QThread
,然后使用 moveToThread
将您的对象移到该线程。
从工作线程发出信号以线程安全地将数据传递到主线程是一种惯用法。例如,假设您希望拥有一个响应灵敏的 GUI 并希望在工作线程中从磁盘加载图像:
class MyWidget : public QWidget {
QLabel m_label;
...
Q_SIGNAL void setImage(const QImage &);
public:
MyWidget() {
...
connect(MyWidget, &MyWidget::setImage, this, [this](const QImage & image){
m_label.setPixmap(QPixmap::fromImage(image));
});
QtConcurrent::run(ioPool(), [this]{ setImage({"/path/to/image.png"}); });
}
};
GUI库
绑定。我认为尽可能使用std::thread
没有任何缺点。 - Galikstd::thread
,比如旧版本的MSVC,那么Qt程序可能是源代码可移植的,而std::thread
应用程序则不是。 - infixedC++
库中寻找解决方案。您必须决定在此实例中使用Qt
所带来的好处。 - Galik