OS-X 10.8.4 を搭載した Mac で Qt 5.1 と QtQuick 2.0 を実行しています。
ファイル I/O 操作でイベント ループをブロックしているため、Qt-QML GUI が応答しなくなります。これを解決するための通常のアプローチは、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) ...
}
これはあまり現実的ではありませんが、以下で遭遇した問題を説明するための簡単なスケッチとして役立ちます。
追加の「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 引数を設定するときの「ファンクター」バインディングの問題が原因である可能性があると思われました (boost がインストールされていないため、boost::bind を使用していません)。:
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:
私は本当にこれでうさぎの穴に落ちました。おそらく単純な間違いですが、それを整理するのに苦労しています.
誰か助けてくれませんか?