QThread问题。 2058年后运行崩溃

时间:2009-10-12 14:58:41

标签: multithreading qt thread-safety

以下线程代码运行2058次,之后崩溃。有人可以帮我找出原因吗?该程序的想法是在主线程中创建一些类,将其传递给工作线程,线程填充所需的数据并将数据传递回主线程。此示例在2058次运行后崩溃,但它应该无限期地进行。我已经运行了20次,总是相同的数字。在简化的qWarning()调用版本中(每100次运行打印简单行),线程执行3000次。所以我猜它不依赖于qWarning()调用的数量。为什么SharedData * d的指针地址总是一样的?

的main.cpp

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    TestThread* thread = new TestThread();

    MainWindow w(thread);
    w.show();

    delete thread;
    return a.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>
#include <QThread>
#include <QHash>

class SharedData
{
    public:
        SharedData();
        QString var;
        QHash<QString, QString> hash;
};

class TestThread : public QThread
{
    Q_OBJECT

    public:
        TestThread(QObject *parent = 0);
        void doWork(SharedData* _data);
        void doCrash(QHash<QString, QString>* hash);
    signals:
        void completed(SharedData* d);
    private:
        SharedData* data;
    protected:
        void run();
};

namespace Ui
{
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(TestThread* t, QWidget *parent = 0);
    ~MainWindow();
    void runThread();
public slots:
    void jobDone(SharedData* req);

private:
    Ui::MainWindow *ui;
    TestThread* t;
    int runcount;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug.h>

TestThread::TestThread(QObject *parent) : QThread(parent)
{
}

void TestThread::run()
{
    qWarning() << "Thread running";
    data->var = "hello";
    doCrash(&data->hash);
    emit completed(data);
}

void TestThread::doWork(SharedData* _data)
{
    data = _data;
    qWarning() << "Attempting to start";
    if(!isRunning())
    {
        run();
    }
    else
    {
        qWarning() << "Oops. Already running";
    }
}

void TestThread::doCrash(QHash<QString, QString>* hash)
{
    hash->insert("test", "123");

    /*
    QHashIterator<QString, QString> i(*hash);
    while (i.hasNext()) {
       i.next();
       qWarning() << i.key() + ":" + i.value();
    }
    */
}

SharedData::SharedData()
{
}

void MainWindow::jobDone(SharedData* req)
{
    qWarning() << "RETURNED";
    qWarning() << "var: " << req->var << " addr: " << &req->var;
    qWarning() << "cnt: " << req->hash.count() << " addr: " << &req->hash;

    QHashIterator<QString, QString> i(req->hash);

    while (i.hasNext()) {
       i.next();
        qWarning() << i.key() + ":" + i.value();
    }

    delete req;
    runThread();
}

MainWindow::MainWindow(TestThread* _t, QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    t = _t;
    connect(t, SIGNAL(completed(SharedData*)), this, SLOT(jobDone(SharedData*)));
    runcount = 0;
    runThread();
}

void MainWindow::runThread()
{
    SharedData* d = new SharedData();
    d->var = "test";

    runcount++;
    qWarning() << "Run count: " << runcount;

    qWarning() << "CREATING THREAD";
    qWarning() << "var: " << d->var << " addr: " << &d->var;
    qWarning() << "cnt: " << d->hash.count() << " addr: " << &d->hash;

    t->doWork(d);
}

MainWindow::~MainWindow()
{
    delete ui;
}

2 个答案:

答案 0 :(得分:2)

你不应该在main.cpp中删除你的TestThread实例(注释掉“删除线程;”字符串)!

答案 1 :(得分:2)

正如vnm所指出的,崩溃的原因很可能是main.cpp中的delete thread;指令:当你调用w.show()它会立即返回时,它是exec()调用将启动事件循环和阻止,但到那时已经太晚了,因为线程已被删除。

我会将该线程声明为主窗口的非指针成员,而不是将其作为参数传递,这样编译器就会为您进行清理和初始化。 更简单的解决方案是使用QtConcurrent::run。通过这样做,您将消除所有显式的踩踏代码,但仍然可以获得多线程的好处。