1

为什么我qtconcurrent::run()的调用和通过对象调用成员函数一样慢?

(例如:QtConcurrent::run(&db, &DBConnect::loadPhoneNumbers)和调用一样慢db.loadPhoneNumbers()

阅读下面的进一步解释

我一直在尝试通过创建一个线程QtConcurrent::run来帮助加快将数据发送到 SQL 数据库表的速度。我正在获取一个 QMap 成员变量并遍历它以将每个键 + 值发送到数据库。

QtConcurrent::run() 调用的成员函数:

void DBConnect::loadPhoneNumbers()
{

//m_phoneNumbers is a private QMap member variable in DBConnect
qDebug() << "\t[!] Items to send: " << m_phoneNumbers.size();

QSqlQuery query;
qDebug() << "\t[!] Using loadphonenumbers thread: " << QThread::currentThread();
qDebug() << "\t[!] Ideal Num of Threads: " << QThread::idealThreadCount();

bool isLoaded = false;

QMap<QString,QString>::const_iterator tmp = m_phoneNumbers.constBegin();

while(tmp != m_phoneNumbers.constEnd())
{
    isLoaded = query.exec(QString("INSERT INTO "+m_mtable+" VALUES('%1','%2')").arg(tmp.key()).arg(tmp.value()));

    if(isLoaded == false)
    {
        qDebug() << "\r\r[X] ERROR: Could\'t load number " << tmp.key() << " into table " << m_mtable;
        qDebug() << query.lastError().text();
    }

    tmp++;
}

}

调用线程的 main.cpp 部分

DBConnect db("QODBC", myINI.getSQLServer(),C_DBASE,myINI.getMTable(), myINI.getBTable());
db.startConnect();

//...more code here

     qDebug() << "\n[*] Using main thread: " << QThread::currentThread() << endl;

         //....two qtconcurrent::run() threads started and finished here (not shown)

         qDebug() << "\n[*] Sending numbers to Database...";
         QFuture<void> dbFuture = QtConcurrent::run(&db, &DBConnect::loadPhoneNumbers);
         dbFuture.waitForFinished();

我对情况的理解

据我了解,该线程将在与主线程分开的新线程池下运行。我所看到的情况并非如此(请注意,在此之前还有 2 个其他 QtConcurrent::run() 调用用于数据库,在继续数据库调用之前全部完成)

现在我考虑使用 QtConcurrent::map() / mapped() 但无法让它与 QMap 一起正常工作。(找不到任何可以帮助的例子,但除此之外......只是一个仅供参考,以防有人问我为什么不使用一个)

一直在做一些“调试”工作来找出发生了什么,在我的测试中,我使用 QThread::currentThread() 来查找我当前正在从哪个线程进行调用。这就是我程序中的各个线程正在发生的事情。(所有 qtconcurrent::run() 调用都是在 main.cpp 中进行的,仅供参考......不确定这是否有区别)

Check what is main thread: on QThread(0x5d2cd0)
Run thread 1: on QThread(0x5dd238, name = "Thread (pooled)")
Run thread 2: on QThread(0x5d2cd0)
Run thread 3 (loadPhoneNumbers function): on QThread(0x5d2cd0)

如上所示,除了第一次qtconcurrent::run()调用外,其他一切都在主线程上(oO)

问题:

据我了解,我所有的线程(全部qtconcurrent::run)都应该在他们自己的线程上(只有第一个是)。这是真的还是我错过了什么?

其次,我的 loadPhoneNumebrs() 成员函数线程安全吗?(因为我没有改变我所看到的任何东西)

最大的问题: 为什么我的loadPhoneNumbers() qtconcurrent::run调用和我刚刚调用成员函数一样慢?(例如:db.loadPhoneNumbers()与 qtconcurrent::run() 版本一样慢)

任何帮助深表感谢!

4

2 回答 2

2

线程不会神奇地加快速度,它们只是让你可以在后台发生时继续做其他事情。当您调用时waitForFinished(),您的主线程将不会继续,直到加载电话号码线程完成,基本上否定了这一优势。根据实现,这可能就是你currentThread()显示与 main 相同的原因,因为等待已经发生。

在速度方面可能更重要的是构建一个插入列表中所有值的单个查询,而不是为每个值单独查询。

于 2012-12-12T00:30:34.130 回答
1

根据 QtSql 文档:

只能在创建它的线程内使用连接。不支持在线程之间移动连接或从不同线程创建查询。

无论如何它都可以工作,因为 ODBC 本身支持对单个 ODBC 句柄的多线程访问。但是由于您只使用一个连接,因此所有查询都可能由 ODBC 序列化,就好像只有一个线程一样(例如,请参阅Oracle 的 ODBC 驱动程序所做的事情)。

waitForFinished()调用一个私有函数stealRunnable(),顾名思义,它从QFuture队列中获取一个尚未启动的任务,并在当前线程中运行它。

于 2012-12-12T19:47:35.537 回答