2017-04-24 63 views
1

我需要同时运行多个(最多50个或更多)Qt脚本函数。使用脚本函数运行两个或三个线程工作得很好,但只要运行50个线程,就会出现一个错误,并且我的程序崩溃。Qt脚本多线程

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脚本线程运行得很好,我不明白是什么造成了这种相反的行为。

+0

您是否尝试在main()中创建线程并将这些对象移动到main()中的线程中? – ni1ight

+0

@ ni1ight只是试了一下。不会改变任何东西。仍然是同样的问题。 – Korboh

回答

0

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

因此,基本上,使用这两种解决方案,您可以创建尽可能多的ScriptEngines,就像调用函数一样? – Korboh

+0

是的,但如果我是正确的,它将共享'globalObject'。不过这是一个猜测,考虑到我是Qt Script的新手。 ;) –