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
Here I register "fun" to be a local property so that when I pop the context, the property is gone. this is to avoid having to register a function I want to call in the global context (as you do). This helps keep the engine clean.
Yes, because you are calling a function that is a property of the global object. Notice the difference between your code creating the function and mine. In my code the function is anonymous.engine.evaluate("fun()"); is enough for me.
lukass (1st March 2012)
Bookmarks