2
  • 平台:Qt 4.8.2(使用 MinGW x64 从源代码构建),Win 7

我使用 QRunnable 将长时间运行的任务与主 GUI 线程分开,有时我会遇到随机崩溃/奇怪的行为,没有可追踪的错误。请帮助提供有关调试内容/方式的建议。谢谢

Runner类:信号/插槽连接到主窗口的多继承

class MyRunner : public QObject, public  QRunnable
{
    Q_OBJECT
Q_SIGNALS:
    void feedbackLog(QString text);
    void finished();
public:
    explicit MyRunner(/* some args */) { /* some initialization */ }

    void run() {
        stopped_ = false;
        for (int run = 0; run < SOME_COUNT; run++) {

            Q_EMIT feedbackLog("Resetting everything ...");
            if (stopped_) return;

            /* start the daily interaction until the epidemic is over */
            do
            {
                if (stopped_) return;
                lengthySubTaskA();
                if (stopped_) return;
                lengthySubTaskB();
                if (stopped_) return;
                lengthySubTaskC();
            }
            while (conditionNotReached());
        } // end: for(run)
        stopped_ = true;
        Q_EMIT finished();
    }
    bool isStopped() { return stopped_; }
public Q_SLOTS:
    void stop() {
        Q_EMIT feedbackLog("Cancel ...");
        stopped_ = true;
    }
private:
    bool stopped_;
    /** other class members follow */
};

主窗口段

void MainWindow::callMyRunnable() {
    runner_ = new MyRunner(/* args */); // runner_ is class member */
    runner_->setAutoDelete(true); // (a)
    progress_dialog_ = new QProgressDialog("Running", "Cancel", 0, 0, this);
    progress_dialog_->setAttribute(Qt::WA_DeleteOnClose);

    connect(runner_, SIGNAL(feedbackLog(QString)), SLOT(logMessage(QString)));
    connect(runner_, SIGNAL(finished()),           SLOT(endLengthyJob()));
    connect(runner_, SIGNAL(finished()), progress_dialog_, SLOT(close()));
    connect(progress_dialog_, SIGNAL(canceled()), runner_, SLOT(stop()));
    connect(progress_dialog_, SIGNAL(canceled()), SLOT(endLengthyJob()));

    QThreadPool::globalInstance()->start(runner_);
    progress_dialog_->show();
    /* flu_runner_->deleteLater(); */ // (b)
}

void MainWindow::closeEvent(QCloseEvent *e) {
     if (runner_ && !runner_->isStopped()) runner_->stop(); // (c)
     if (QThreadPool::globalInstance()->activeThreadCount())
     {
         /* display a dialog to notify user about shutdown */
         Dialog::WaitDialog dlg(5 * 1000);
         dlg.exec();
     }
     event->accept();
} // end_event(MainWindow::closeEvent)

1)如果我在(a)处禁用自动删除,我应该添加语句(b)以防止泄漏吗?或者有什么更好的方法来处理泄漏?

2)有时,当 Runnable 任务完成时,我无法正常关闭应用程序([x] 按钮和 Alt-F4 都不起作用),我必须从 QtCreator 中终止应用程序(我正在调试,对吗?)。这可能是什么原因?

[编辑]: 3) 对于不可关闭的主窗口,有时会在我取消 MyRunner 类处理的任务后发生,这可能是原因吗?

[编辑]:我在 (c) 周围添加了 qDebug() 语句,发现它在 (c) 处停止并拒绝继续显示等待对话框,以防 [x] 按钮没有响应。

谢谢。

4

1 回答 1

2

通过更改主窗口的“关闭策略”来解决该问题:删除“自动杀死”并强制用户等待产生的线程。变量runner_progress_dialog_现在本地化到函数callMyRunnable()

于 2013-05-22T01:52:11.977 回答