2017-04-24 84 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的新手。 ;) –