我在运行OS-X 10.8.4的Mac上运行Qt 5.1和QtQuick 2.0。
我的Qt-QML GUI变得无法响应,因为我使用文件I / O操作阻止了事件循环。解决它的常用方法是使用Will Bickford所讨论的HERE多线程。
为此,我试图使用:
QtConcurrent::blockingMapped()
可以比使用显式QFuture对象更简单。我一直在阅读Qt docs和cool examples并获得以下代码(模仿此example后):
// 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) ...
}
这不太现实,但可以作为一个简单的草图来说明我在下面遇到的问题。
当我尝试在另外的“datamodel.h”类中封装QtConcurrent :: blockingMapped()时会出现问题:
#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参数时出现“functor”绑定问题(我没有安装boost,所以我没有使用boost::bind)所以我试过Mat's suggestion通过替换:
使用C ++ 11 lambdathis->load
with:
[this](const QString& file){load(file);}
给出代码:
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles,
[this](const QString& file){load(file);});
现在我不再获得非静态成员错误,但发生了新错误(指向上面一行):
datamodel.cpp: error: expected expression:
我真的在这个问题上遇到了一个兔子洞,这可能是一个简单的错误,但我无法将其整理出来。
有人可以帮忙吗?
答案 0 :(得分:0)
显然你不使用具有lambda表达式的C ++ 11。因此,请使用STL或Boost绑定或创建函数对象。
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles,
std::bind1st(std::mem_fun(&DataModel::load), this));
Ok以上解决方案无法使用引用(知道bug)。定义仿函数(或使用Boost :: bind):
class LoadDataModel /*: public std::unary_function<QString, DataObject>*/ {
public:
LoadDataModel(DataModel *p) : d(p) {}
DataObject operator()(const QString &s) const {
return d->load(s);
}
private:
DataModel *d;
}
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles, LoadDataModel(this));
答案 1 :(得分:0)
好的,让它上班。
如果这可能会使那些可能不想搞乱绑定或编写自己的“仿函数”的人受益(下面的方法更简单):
首先在datamodel.h文件中使用静态类型作为“load”函数:
static DataObject load(const QString& fileList);
这是有效的,因为可以在不需要实例化对象的情况下调用C ++类的静态函数。
然后,在datamodel.cpp文件中,就是这么简单:
DataModel::load
给予:
QList<DataObject> allTheDataObjects =
QtConcurrent::blockingMapped(allFiles, DataModel::load);
然后代码按预期运行。