Hello,
QScriptValue::call() can block thread. Is there any way to abort QScriptValue::call()? I tried to use QScriptEngine::abortEvaluation(), but this not working. Can anyone help?
Hello,
QScriptValue::call() can block thread. Is there any way to abort QScriptValue::call()? I tried to use QScriptEngine::abortEvaluation(), but this not working. Can anyone help?
Are you calling a javascript function or a native one?
I'm calling JS function:
Qt Code:
function init() { for(var i = 0; i < 9000000000; ++i) for(var j = 0; j < 9000000000; ++j) var x = 10; }To copy to clipboard, switch view to plain text mode
The script engine periodically calls processEvents(), so if you want to abort a call, you would have to do that using an event or as a result of a timer signal being emitted.
Yes, I know. I do this, but not working!
In C++ I initialize:
engine is object of QScriptEngine.Qt Code:
engine.setProcessEventsInterval(100); wait_dialog->setValue(-1); connect(wait_dialog, SIGNAL(canceled()), SLOT(wait_dialog_canceled()));To copy to clipboard, switch view to plain text mode
Now I run script:
When I click 'Cancel' in wait_dialog then:Qt Code:
wait_dialog->show(); QScriptValue init_funct = engine.evaluate("init"); init_funct.call(this_object);To copy to clipboard, switch view to plain text mode
but 'init_funct.call(this_object);' is still running and blocking thread periodically.Qt Code:
void sth_engine::wait_dialog_canceled() { engine.abortEvaluation(); }To copy to clipboard, switch view to plain text mode
I didn't say anything about clicking any buttons.Yes, I know. I do this,
Ok, here is example with timer.
Initialization:
Qt Code:
engine.setProcessEventsInterval(100); this_object = engine.newQObject(this); timer->setSingleShot(true); connect(timer, SIGNAL(timeout()), SLOT(timeout()));To copy to clipboard, switch view to plain text mode
I run script:
Qt Code:
QScriptValue init_funct = engine.evaluate("init"); timer->start(10000); init_funct.call(this_object);To copy to clipboard, switch view to plain text mode
If timer timeout then:
but after 10 seconds 'init_funct.call(this_object);' is still running and blocking thread periodically.Qt Code:
void sth::timeout() { engine.abortEvaluation(); }To copy to clipboard, switch view to plain text mode
Apparently you are doing something wrong. This works just fine:
Qt Code:
#include <QScriptEngine> #include <QtCore> Q_OBJECT public: Object() { connect(&timer, SIGNAL(timeout()), this, SLOT(abort())); engine.setProcessEventsInterval(1000); } void startEval() { timer.start(1000); engine.evaluate("while(true);"); } private slots: void abort() { static int cnt = 0; bool ev = engine.isEvaluating(); qDebug() << "isEvaluating?" << ev; if(!ev) timer.stop(); ++cnt; if(cnt==5) { qDebug() << "Aborting evaluation"; engine.abortEvaluation(); } } private: QScriptEngine engine; QTimer timer; }; #include "main.moc" int main(int argc, char **argv){ Object o; o.startEval(); // return app.exec(); return 0; }To copy to clipboard, switch view to plain text mode
The topic is: Is there any way to abort QScriptValue::call() ? and you give me example code with QSciptEngine::evaluate().
Ok, here my full example:
results: "isEvaluating? false" and 'init_funct.call(this_object);' is still running and blocking thread [strike]periodically[/strike].Qt Code:
#include <QScriptEngine> #include <QtCore> Q_OBJECT public: Object() { connect(&timer, SIGNAL(timeout()), this, SLOT(abort())); engine.setProcessEventsInterval(1000); this_object = engine.newQObject(this); } void startEval() { engine.evaluate( "function init()" "{" " for(var i = 0; i < 9000000000; ++i)" " for(var j = 0; j < 9000000000; ++j)" " var x = 10;" "}"); QScriptValue init_funct = engine.evaluate("init"); timer.start(1000); init_funct.call(this_object); qDebug() << "end of startEval()"; } private slots: void abort() { static int cnt = 0; bool ev = engine.isEvaluating(); qDebug() << "isEvaluating?" << ev; if(!ev) timer.stop(); ++cnt; if(cnt==5) { qDebug() << "Aborting evaluation"; engine.abortEvaluation(); } } private: QScriptEngine engine; QTimer timer; QScriptValue this_object; }; #include "main.moc" int main(int argc, char **argv){ Object o; o.startEval(); // return app.exec(); return 0; }To copy to clipboard, switch view to plain text mode
Last edited by lukass; 29th February 2012 at 17:30. Reason: [strike]periodically[/strike]
Qt Code:
Q_OBJECT public: Object() { connect(&timer, SIGNAL(timeout()), this, SLOT(abort())); engine.setProcessEventsInterval(1000); fun = engine.evaluate("(function() { while(true); })"); } void startEval() { timer.start(1000); qDebug() << "is callable?" << fun.isFunction(); QScriptContext *context = engine.pushContext(); QScriptValue v = context->activationObject(); v.setProperty("fun", fun); engine.evaluate("fun()"); engine.popContext(); } private slots: void abort() { bool ev = engine.isEvaluating(); qDebug() << "isEvaluating?" << ev; qDebug() << "Aborting evaluation"; engine.abortEvaluation(); } private: // ... QScriptValue fun; //... };To copy to clipboard, switch view to plain text mode
This calls the function and aborts it after one second. QScriptValue::call() itself doesn't seem abortable as it is executed using different JavaScriptCore method than evaluate(). If you want more flexibility you can probably make your function the activation object itself, set needed arguments and trigger the context (somehow).
lukass (29th February 2012)
Thanks, this works!
However I not fully understand what for is these 4 lines:
engine.evaluate("fun()"); is enough for me.Qt Code:
QScriptContext *context = engine.pushContext(); QScriptValue v = context->activationObject(); v.setProperty("fun", fun); engine.popContext();To copy to clipboard, switch view to plain text mode
Bookmarks