【问题标题】:How to deal: "Duplicate connection..." and "Timers cannot be stopped from another thread..."如何处理:“重复连接...”和“计时器不能从另一个线程停止...”
【发布时间】:2021-04-13 01:24:46
【问题描述】:

我有一个非常大的文件,其中包含简单的结构化 XML 数据(大约 180,000 条记录)。我需要一个显示进度条并使用另一个线程将数据解析到数据库的对话框。困难之一是我需要写入数据的数据库已被主窗口使用。

应用做什么:

  1. MainWindow 打开数据库并使用它。
  2. 如果单击“解析并写入”操作,则主窗口:(我们的对话)
void MainWindow::on_act_parse_and_write()
{
    // CLOSE DB
    db->close();
    delete db;
    
    // EXEC DLG
    update_omega_base * dlg = new update_omega_base(this);
    dlg->exec();

    // OPEN NEW CONNECTION
    db = new QSqlDatabase();
    *db = QSqlDatabase::addDatabase("QSQLITE");
    db->setDatabaseName(DB_NAME);
    if (!db->open()) {
        QMessageBox::critical(nullptr, "Помилка", "Не можу підключити базу даних MAINWINDOW", QMessageBox::Ok);
        exit(ERROR_CODE);
    }
}
  1. 我的 dlg 创建了一个 gui:

  1. 如果单击左键,则程序会创建一个新线程并编辑进度条:
    parse_and_writeToDB *worker = new parse_and_writeToDB();
    worker->moveToThread(&workThread);

    connect(&workThread, &QThread::finished, &workThread, &QObject::deleteLater);
    connect(this, &update_omega_base::startWork, worker, &parse_and_writeToDB::doWork);
    connect(worker, &parse_and_writeToDB::currentRowChanged, this, &update_omega_base::updateCurrentProgress);
    connect(worker, &parse_and_writeToDB::errorDetected, this, &update_omega_base::handleError);

    workThread.start();
  1. “parse_and_writeToDB”类中的doWork():
    // CREATE CONNECTION TO DATABASE
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(DB_NAME);
    if (!db.open()) {
        emit errorDetected("Не можу відкрити базу даних");
        exit(ERROR_CODE);
    }

    QSqlQuery qry;

    // clear old Omega table
    if(!qry.exec("DELETE FROM " + DB_TABLE_OMEGA))
    {
        emit errorDetected("Не виходить очистити БД перед записом");
        exit(ERROR_CODE);
    }

    // ------- QXmlStreamParser PARSES EVERYTHING and qry ADDS ROWS -------

    qry.clear();
    db.close();
  1. 工作一段时间后,应用程序崩溃。输出:
QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.
QObject::~QObject: Timers cannot be stopped from another thread

UPDATE #1 - invodeMethod - 太慢了,无论如何工作都是使用主线程完成的。在写入 DB gui 的过程中感觉很糟糕。

【问题讨论】:

  • 所以你真正的问题是“如何从多个线程访问数据库”,对吧?按照here 的说明,尝试重命名您的连接。
  • @JarMan 不,我真正的问题是“为什么我会出现这样的错误?我认为我做的一切都是正确的。”

标签: c++ multithreading sqlite qt


【解决方案1】:

您可以从不同的线程调用 metaCall。 像这样:

QMetaObject::invokeMethod(obj, "slot",
                            Qt::QueuedConnection);

obj是QObject指针,“slot”是你定义为“public SLOTS”的函数

【讨论】:

  • 你检查 invokeMethod 的返回值吗?我的意思是 bool bRet = QMetaObject::invokeMethod(parent, "addRowToDB", Qt::QueuedConnection, );如果 bRet = true ,则该方法将执行。否则检查参数。
  • 是的,invokeMethod 的一切都很好。有 2 个问题:1)我在解析 90 多行 xml 文件时遇到的错误。 2) 太慢了。无论如何,使用 db 的工作是使用主线程完成的,这就是 gui 感觉不好的原因。现在,我看到我需要找到使用另一个线程编写数据库的路径(每个线程创建新数据库的解决方案对我不利)。无论如何,谢谢你)
猜你喜欢
  • 1970-01-01
  • 2021-10-23
  • 1970-01-01
  • 2020-03-31
  • 1970-01-01
  • 2014-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多