Здравствуйте. Я работаю над приложением, которое должно выводить случайную игру на определенную платформу. Для того, чтобы приложение казалось не совсем "сухим" и скучным я решил добавить эффект перелистывания игр, чтобы пользователь мельком увидел еще пару десятков игр на эту платформу. Хотя о многопоточности знаю только по теории и наслышке, сразу подумал о ней, но так как класс модели (класс Model) у меня синхнонный, а асинхронность нужна только для одного метода решил создать еще один класс, который и унаследовал от QThread (класс AsyncRoller). Он принимает указатель на модель и имя платформы в конструкторе и просто вызывает метод из модели, переданной в конструктор. Соответственно, десяток-другой таких потоков я создаю в представлении (нутром чую, что это говнорешение). Ну, так как в многопоточности не сильно смыслю, налепил мьютекс на метод ролла, чтобы потоки не лезли вне очереди. В результате выходит быстрое перелистывание пары игр (1-2). Как синхнонизировать это?
//model.h
class Model: public QObject
{
Q_OBJECT
Q_PROPERTY(QString rggGame READ game WRITE setGame NOTIFY gameSet)
private:
QString currentGame;
public:
Model(QStringList _platform, QObject* _parent = nullptr);
QString game();
public slots:
Q_INVOKABLE void rollGame(QString _platform);
Q_INVOKABLE void asyncRollGame(QString _platform);
Q_INVOKABLE void setGame(QString _game);
signals:
void gameRolled(QString _game);
void gameSet(QString _game);
};
//model.cpp
//...
void Model::rollGame(QString _platform)
{
static QMutex mute;
mute.lock();
QVector<QString> gms;
QFile games(platformAssignment.value(_platform));
if(!games.open(QIODevice::ReadOnly))
qDebug() << "Error opening platform file!";
while(!games.atEnd())
gms.append(QString::fromStdString(games.readLine().toStdString()));
srand(time(0));
QString gameName = gms[rand() % gms.size()];
emit gameRolled(gameName);
setGame(gameName);
mute.unlock();
}
void Model::asyncRollGame(QString _platform)
{
AsyncRoller* roller = new AsyncRoller(this, _platform);
roller->start();
}
void Model::setGame(QString _game)
{
this->currentGame = _game;
emit gameSet(this->currentGame);
}
//AsyncRoller.h
class AsyncRoller : public QThread
{
private:
Model* model;
QString platform;
public:
AsyncRoller();
AsyncRoller(Model* _mdl, QString _platform);
void run();
};
//AsyncRoller.cpp
AsyncRoller::AsyncRoller(Model* _mdl, QString _platform)
{
model = _mdl;
platform = _platform;
}
void AsyncRoller::run()
{
model->rollGame(platform);
}