0

我正在通过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();
    }
}

现在在调用我的应用程序之前,在打印和调用我的应用程序的内存使用量达到 26MBprint()之后会暴露大约 9MB 的内存PrintWorker::print()

在另一个世界中,如果我们删除emit done最后一部分,PrintWorker::print()它没有任何区别。

完成工作后我们期望内存使用量应降至 26MB - 线程空间 + _printer+_printDialog对象大小 ≈ 14MB

那么这有什么问题呢?

4

2 回答 2

0

通过调用QThread::quit(),您将主动退出此线程中的 EventLoop。驻留在此线程中的QObject::deleteLater()for 对象可能不再执行(尽管他们在QThread::finished()-signal 上提到删除稍后的插槽仍将被调用)。

我个人只是使​​用finished()信号设置连接或将工作对象的父级设置为线程本身,然后 Qt 实际上必须删除该对象。

http://doc.qt.io/qt-5/qthread.html#exit

于 2017-01-04T13:25:22.723 回答
0

您正在删除PrintWorkerQThread对象,但不是QPainter, QPicture, MyWidget, QPrintDialognor QPrinter。这些是内存泄漏(new没有delete)。请注意,PrintWorker析构函数可以负责删除和QPainter,此外,它还可以拥有并删除它。希望对象被类删除,但很难说,因为代码没有发布。QPictureQPrinterMyWidgetQPrintDialogNewService

此外,正如 rafael gonzalez 所推荐的那样,您应该检查QThread PrintWorkerQThread实际被删除。

顺便问一下,您是如何检查内存使用情况的?通过泄漏检测工具(如 valgrind、VLD...)?或通过 Windows 任务管理器。因为任务管理器肯定是不准确的。

于 2017-01-04T10:48:58.720 回答