我正在使用QThread
通过QPrinter
打印工作
我的PrintWorker
看起来像这样:
class PrintWorker : public QObject {
Q_OBJECT
public:
PrintWorker(QThread*, QPrinter*, QPicture*, QPainter*, QObject *parent = 0);
private:
QPicture *_picture = nullptr;
QPrinter *_printer = nullptr;
QPainter *_painter = nullptr;
public slots:
void print();
signals:
void done();
};
PrintWorker::PrintWorker(QThread *thread, QPrinter *printer, QPicture *picture, QPainter *painter, QObject *parent) :QObject(parent),
_picture(picture), _printer(printer), _painter(painter)
{
moveToThread(thread);
QObject::connect(thread, &QThread::started, this, &PrintWorker::print);
QObject::connect(this, &PrintWorker::done, thread, &QThread::quit);
QObject::connect(this, &PrintWorker::done, this, &PrintWorker::deleteLater);
QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater);
}
void PrintWorker::print() {
// do some print job with painter and picture
emit done();
}
print
方法是这样的:
void NewService::print() {
if (!_printer) { /* _printer : a private member */
_printer = new QPrinter(QPrinter::HighResolution);
_printer->setPageSize(QPrinter::A5);
_printer->setPageOrientation(QPageLayout::Portrait);
_printer->setColorMode(QPrinter::Color);
}
if (!_printDialog) { /* _printDialog : a private member */
_printDialog = new QPrintDialog(_printer);
}
if (_printDialog->exec() == QPrintDialog::Accepted) {
MyWidget *widget = new MyWidget(/* some args*/);
QPainter *painter = new QPainter;
QPicture *picture = new QPicture;
widget->render(picture);
QThread *thread = new QThread;
PrintWorker *worker = new PrintWorker(thread, _printer, picture, painter);
thread->start();
}
}
现在,在调用print()
我的应用程序在打印和调用后公开大约 9MB 的内存PrintWorker::print()
我的应用程序的内存使用量达到 26MB
在另一个世界,如果我们在PrintWorker::print()
的最后部分删除emit done
,那就没有区别了。
完成作业后,我们期望内存使用量应降至 26MB - 线程空间 + _printer
+ _printDialog
对象大小≈ 14MB
那么这有什么问题呢?
您正在删除PrintWorker
和QThread
对象,但不会删除QPainter
、QPicture
、MyWidget
、QPrintDialog
或QPrinter
。这些是内存泄漏(new
没有delete
)。请注意,PrintWorker
析构函数可以负责删除QPainter
、QPicture
和QPrinter
,此外,它还可以获得MyWidget
的所有权并删除它。希望QPrintDialog
对象被类删除NewService
但很难说,因为代码没有发布。
此外,正如拉斐尔·冈萨雷斯(rafael Gonzalez)所建议的那样,您应该检查QThread
PrintWorker
和QThread
是否确实被删除。
顺便问一下,您是如何检查内存使用情况的?通过泄漏检测工具(如瓦尔格林德,VLD等)?或通过Windows任务管理器。因为任务管理器绝对是不准确的。
通过调用QThread::quit()
,您将主动退出此线程中的 EventLoop。驻留在此线程中的对象的QObject::deleteLater()
可能不再执行(尽管它们在 QThread::finished()
-signal 上提到稍后删除槽仍将被调用)。
我个人只会使用 finished()
信号设置连接,或者将 worker-对象的父级设置为线程本身,然后 Qt 实际上必须删除该对象。
http://doc.qt.io/qt-5/qthread.html#exit