我在装有 OS-X 10.8.4 的 Mac 上运行 Qt 5.1 和 QtQuick 2.0。
我的 Qt-QML GUI 变得无响应,因为我用文件 I/O 操作阻塞了事件循环。解决它的常用方法是使用Will Bickford在此处讨论的多个线程。
为此,我正在尝试使用:
QtConcurrent::blockingMapped()
这比使用显式 QFuture 对象更简单。我一直在阅读Qt 文档和很酷的示例,并获得了以下代码(仿照此示例):
// NOTE: this all seems to work:
#include <QList>
#include <iostream>
#include "dataobject.h"
#include <QtConcurrent/QtConcurrentMap>
DataObject load(const QString &file) {
std::cout << "File I/O in thread = " << QThread::currentThread() << std::endl;
return DataObject anObject(file);
}
int main(int argc, char *argv[])
{
...
// Create a list of filenames:
int count = 5;
QList<QString> allFiles;
for (int i = 0; i < count; i++) {
allFiles.append(QString("aFileName"));
}
std::cout << "# of files = " << allFiles.size() << std::endl;
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles,load);
std::cout << "# of objects = " << allTheDataObjects.size() << std::endl;
...
}
以下是 DataObject 的头文件和实现文件:
#include <QString>
class DataObject
{
public:
DataObject();
DataObject(QString filename);
QString theFileName;
};
#include "dataobject.h"
DataObject::DataObject() {
theFileName = QString("no file");
}
DataObject::DataObject(QString filename) {
theFileName = filename;
//...
// Do file I/O stuff (slow) ...
}
这不是很现实,但可以作为一个简单的草图来说明我在下面遇到的问题。
当我尝试将 QtConcurrent::blockingMapped() 封装在一个额外的“datamodel.h”类中时,就会出现问题:
#include "dataobject.h"
class DataModel
{
public:
DataModel();
void runConcurrent();
DataObject load(const QString& fileList);
};
#include "datamodel.h"
#include <QtConcurrent/QtConcurrentMap>
#include <iostream>
DataModel::DataModel() {}
DataObject DataModel::load(const QString &file) {
std::cout << "File I/O in thread = " << QThread::currentThread() << std::endl;
return DataObject anObject(file);
}
void DataModel::runConcurrent() {
// Create a list of filenames:
int count = 5;
QList<QString> allFiles;
for (int i = 0; i < count; i++)
allFiles.append(QString("dummyFileName"));
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles, this->load);
std::cout << "# of objects = " << allTheDataObjects.size() << std::endl;
}
然后 main() 变成了(注意我也把 load() 方法移到了 DataModel 类中):
#include <QList>
#include <iostream>
#include "dataobject.h"
#include "datamodel.h"
#include <QtConcurrent/QtConcurrentMap>
int main(int argc, char *argv[])
{
...
DataModel theModel;
theModel.runConcurrent();
...
}
但是现在有一个编译器错误:
datamodel.cpp: error: reference to non-static member function must be called:
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles, this->load);
我无法通过初始化 DataObject 或 DataModel 实例来修复编译器错误(以便可以看到非静态成员函数),并且不确定还有什么可以尝试的。
接下来,我怀疑这可能是由于设置 QtConcurrent 参数时“函子”绑定的问题(我没有安装 boost,所以没有使用boost::bind)所以我尝试了Mat 的建议,即通过替换使用 C++ 11 lambdas :
this->load
和:
[this](const QString& file){load(file);}
给出代码:
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles,
[this](const QString& file){load(file);});
现在我不再收到非静态成员错误,而是出现了一个新错误(指向上面的行):
datamodel.cpp: error: expected expression:
我真的在这个问题上陷入了困境,这可能是一个简单的错误,但我很难把它整理出来。
有人可以帮忙吗?