Qt 脚本多线程
Qt Script Multithreading
我需要同时 运行 多个(最多 50 个或更多)Qt 脚本函数。 运行 两个或三个具有脚本函数的线程工作得很好,但是当我 运行 大约 50 个线程时,我得到一个错误并且我的程序崩溃了。
ASSERTION FAILED: globalData().dynamicGlobalObject (..rdparty\javascriptcore\JavaScriptCore\runtime/JSGlobalObject.h:411 QTJSC::JSGlobalObject* QTJSC::ExecState::dynamicGlobalObject())
我的 main.cpp 看起来像这样:
#include <QCoreApplication>
#include <QScriptEngine>
#include <threadworker.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QScriptEngine engine;
QScriptValue val = engine.evaluate("(function() {var r = Math.random(); while(1>0) print(r);})");
ThreadWorker *worker[50];
for(int i=0;i<50;i++) {
worker[i] = new ThreadWorker(val);
QObject::connect(worker[i], SIGNAL(needsStarting()), worker[i], SLOT(startScript()));
emit worker[i]->needsStarting();
}
return a.exec();
}
这是我的 threadworker.h:
#ifndef THREADWORKER_H
#define THREADWORKER_H
#include <QObject>
#include <QScriptValue>
#include <QThread>
class ThreadWorker : public QObject
{
Q_OBJECT
public:
explicit ThreadWorker(QObject *parent = 0);
explicit ThreadWorker(QScriptValue function);
signals:
needsStarting();
public slots:
void startScript();
private:
QScriptValue value;
QThread thread;
};
#endif // THREADWORKER_H
这是我的 threadworker.cpp:
#include "threadworker.h"
#include <QDebug>
ThreadWorker::ThreadWorker(QObject *parent) : QObject(parent)
{
}
ThreadWorker::ThreadWorker(QScriptValue function)
{
value = function;
this->moveToThread(&thread);
thread.start();
}
void ThreadWorker::startScript()
{
value.call();
}
我预计,无论数量如何,Qt 脚本线程 运行 都很好,我不明白是什么导致了这种相反的行为。
将 QScriptEngine
放在工作线程 class 上并让 moveToThread
将其移动到工作线程,似乎可以解决:
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
public slots:
void startScript(const QString &function);
private:
QScriptEngine engine;
QScriptValue value;
};
但是,创建如此多的线程并在应用程序退出时正确释放它们将是一个挑战。我建议您使用线程池,例如 QtConcurrent
。 QtConcurrent
允许您(例如但不限于)仅具有功能的多线程,不一定是 classes,并且具有 QFutureSyncronyzer
you can in one call wait for all the threads you want to finish. See QtConcurrent
:
#include <QtScript>
#include <QtConcurrent>
#define THREADS 50
void worker_function(const QString &function)
{
QScriptEngine engine;
QScriptValue value;
value = engine.evaluate(function);
value.call();
}
...
QFutureSynchronizer<void> synchronizer;
//Set the max pooled threads
QThreadPool::globalInstance()->setMaxThreadCount(THREADS);
//Start all threads and add them to the future synchronizer
for (int i = 0; i < THREADS; i++)
synchronizer.addFuture(QtConcurrent::run(worker_function, QString("(function() {var r = Math.random(); while(1>0) print(r);})")));
//Wait for all threads to finish
synchronizer.waitForFinished();
...
我需要同时 运行 多个(最多 50 个或更多)Qt 脚本函数。 运行 两个或三个具有脚本函数的线程工作得很好,但是当我 运行 大约 50 个线程时,我得到一个错误并且我的程序崩溃了。
ASSERTION FAILED: globalData().dynamicGlobalObject (..rdparty\javascriptcore\JavaScriptCore\runtime/JSGlobalObject.h:411 QTJSC::JSGlobalObject* QTJSC::ExecState::dynamicGlobalObject())
我的 main.cpp 看起来像这样:
#include <QCoreApplication>
#include <QScriptEngine>
#include <threadworker.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QScriptEngine engine;
QScriptValue val = engine.evaluate("(function() {var r = Math.random(); while(1>0) print(r);})");
ThreadWorker *worker[50];
for(int i=0;i<50;i++) {
worker[i] = new ThreadWorker(val);
QObject::connect(worker[i], SIGNAL(needsStarting()), worker[i], SLOT(startScript()));
emit worker[i]->needsStarting();
}
return a.exec();
}
这是我的 threadworker.h:
#ifndef THREADWORKER_H
#define THREADWORKER_H
#include <QObject>
#include <QScriptValue>
#include <QThread>
class ThreadWorker : public QObject
{
Q_OBJECT
public:
explicit ThreadWorker(QObject *parent = 0);
explicit ThreadWorker(QScriptValue function);
signals:
needsStarting();
public slots:
void startScript();
private:
QScriptValue value;
QThread thread;
};
#endif // THREADWORKER_H
这是我的 threadworker.cpp:
#include "threadworker.h"
#include <QDebug>
ThreadWorker::ThreadWorker(QObject *parent) : QObject(parent)
{
}
ThreadWorker::ThreadWorker(QScriptValue function)
{
value = function;
this->moveToThread(&thread);
thread.start();
}
void ThreadWorker::startScript()
{
value.call();
}
我预计,无论数量如何,Qt 脚本线程 运行 都很好,我不明白是什么导致了这种相反的行为。
将 QScriptEngine
放在工作线程 class 上并让 moveToThread
将其移动到工作线程,似乎可以解决:
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
public slots:
void startScript(const QString &function);
private:
QScriptEngine engine;
QScriptValue value;
};
但是,创建如此多的线程并在应用程序退出时正确释放它们将是一个挑战。我建议您使用线程池,例如 QtConcurrent
。 QtConcurrent
允许您(例如但不限于)仅具有功能的多线程,不一定是 classes,并且具有 QFutureSyncronyzer
you can in one call wait for all the threads you want to finish. See QtConcurrent
:
#include <QtScript>
#include <QtConcurrent>
#define THREADS 50
void worker_function(const QString &function)
{
QScriptEngine engine;
QScriptValue value;
value = engine.evaluate(function);
value.call();
}
...
QFutureSynchronizer<void> synchronizer;
//Set the max pooled threads
QThreadPool::globalInstance()->setMaxThreadCount(THREADS);
//Start all threads and add them to the future synchronizer
for (int i = 0; i < THREADS; i++)
synchronizer.addFuture(QtConcurrent::run(worker_function, QString("(function() {var r = Math.random(); while(1>0) print(r);})")));
//Wait for all threads to finish
synchronizer.waitForFinished();
...