QT脚本多线程

Qt Script Multithreading

本文关键字:多线程 脚本 QT      更新时间:2023-10-16

我需要同时运行多个(最多50或更多(QT脚本功能。使用脚本函数运行两个或三个线程正常工作,但是一旦我在50个线程围绕50个线程运行,我就会遇到一个错误,并且程序崩溃了。

ASSERTION FAILED: globalData().dynamicGlobalObject (..3rdpartyjavascriptcoreJavaScriptCoreruntime/JSGlobalObject.h:411 QTJSC::JSGlobalObject* QTJSC::ExecState::dynamicGlobalObject())

我的主要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放在工作类上,让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;
};

但是,这将是一个挑战,创建如此多的线程并在应用程序退出时正确释放它们。我建议您使用合并的线程,例如QtConcurrentQtConcurrent允许您(例如,但不限于(仅具有功能,不必要类的多线程,并且使用QFutureSyncronyzer,您可以在一次呼叫中等待所有要完成的线程。参见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();
...