QtConcurrent线程很慢!!我究竟做错了什么?

时间:2012-12-11 23:00:35

标签: multithreading qt thread-safety qtsql qtconcurrent

为什么我的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();

我对情况的理解

根据我的理解,这个线程将在一个与主线程分开的新线程池下运行。我所看到的情况并非如此(请注意,在此之前还有另外两个QtConcurrent :: run()调用数据库,在继续数据库调用之前完成所有操作)

现在我想过使用QtConcurrent :: map()/ mapped()但是无法使它与QMap一起正常工作。 (找不到任何例子来帮助解决这个问题,但除此之外......只是一个FYI,以防有人问为什么我没有使用一个)

一直在做一些“调试”工作,以找出发生了什么,在我的测试中,我使用QThread :: currentThread()来查找我正在调用的线程。这是我的程序中的各种线程正在发生的事情。 (所有qtconcurrent :: run()调用都在main.cpp FYI中进行...不确定是否有所不同)

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()调用之外,其他所有内容都在主线程上(o.O)

问题:

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

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

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

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

根据QtSql文档:

  

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

它仍然有效,因为ODBC本身支持对单个ODBC句柄的多线程访问。但由于您只使用一个连接,因此所有查询都可能由ODBC序列化,就好像只有一个线程一样(参见例如what Oracle's ODBC driver does)。

waitForFinished()调用私有函数stealRunnable(),正如其名称所暗示的那样,从QFuture队列中获取尚未启动的任务,并在当前线程中运行它。