Qt 脚本多线程

Posted

技术标签:

【中文标题】Qt 脚本多线程【英文标题】:Qt Script Multithreading 【发布时间】:2017-04-24 10:20:28 【问题描述】:

我需要同时运行多个(最多 50 个或更多)Qt 脚本函数。使用脚本函数运行两个或三个线程就可以了,但是当我运行大约 50 个线程时,我得到一个错误并且我的程序崩溃了。

ASSERTION FAILED: globalData().dynamicGlobalObject (..\3rdparty\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 脚本线程都可以正常运行,但我不明白是什么导致了这种相反的行为。

【问题讨论】:

您是否尝试在 main() 中创建线程并将这些对象也移动到 main() 中的那些线程中? @ni1ight 刚刚尝试过。不会改变任何东西。还是一样的问题。 【参考方案1】:

QScriptEngine 放在worker 类上,让moveToThread 将其移至worker 线程,似乎可以解决:

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();
...

【讨论】:

所以基本上,使用这两种解决方案,您创建的 ScriptEngine 与进行函数调用一样多? 是的,但如果我是正确的,它将分享globalObject。然而这是一个猜测,考虑到我是 Qt 脚本的新手。 ;)

以上是关于Qt 脚本多线程的主要内容,如果未能解决你的问题,请参考以下文章

qt多线程的问题

QT多线程问题:子线程中的变量如何传递给主线程?

QT开发(三十四)——QT多线程编程

QT中的信号与事件,多线程

qt多线程中怎样锁定一个指定的变量?

Qt多线程——方式2