Я оцениваю JavaScript в своем приложении Qt, используя QScriptEngine::evaluate(QString code)
. Допустим, я оцениваю ошибочный фрагмент JavaScript, который зацикливается навсегда (или занимает слишком много времени, чтобы дождаться результата). Как я могу выкинуть такое исполнение?
Я хочу контролировать оценку с помощью двух кнопок Run
а также Abort
в графическом интерфейсе (Но одновременно разрешено только одно исполнение.)
Я думал о запуске сценария через QtConcurrent::run
, сохраняя QFuture
и звонит cancel()
когда Abort
был нажат. Но в документации сказано, что я не могу отменить такие казни. Это похоже на QFuture
отменяется только после обработки текущего элемента в задании, т.е. при уменьшении или фильтрации коллекции. Но для QtConcurrent::run
это означает, что я не могу использовать будущее, чтобы прервать его выполнение.
Другая возможность, которую я придумал, это использование QThread
и звонит quit()
, но там у меня есть похожие проблемы: он отменяет поток, только если / как только он ожидает в цикле событий. Но так как мое выполнение — единственный вызов функции, это тоже не вариант.
QThread
также имеет terminate()
, но документация заставляет меня немного волноваться. Хотя сам мой код не включает мьютексы, возможно QScriptEngine::evaluate
делает за кадром?
Предупреждение: Эта функция опасна, и ее использование не рекомендуется. Поток может быть прерван в любой точке пути кода. Потоки могут быть прерваны при изменении данных. Поток не может очистить после себя, разблокировать все удержанные мьютексы и т. Д. Короче говоря, используйте эту функцию только в случае крайней необходимости.
Есть ли другой вариант, который мне не хватает, может быть, какая-то функция асинхронной оценки?
http://doc.qt.io/qt-4.8/qscriptengine.html#details
В нем есть несколько разделов, посвященных вашим проблемам:
http://doc.qt.io/qt-4.8/qscriptengine.html#long-running-scripts
http://doc.qt.io/qt-4.8/qscriptengine.html#script-exceptions
http://doc.qt.io/qt-4.8/qscriptengine.html#abortEvaluation
http://doc.qt.io/qt-4.8/qscriptengine.html#setProcessEventsInterval
Надеюсь, это поможет.
Хотя сама параллельная задача не может быть прервана «извне», QScriptEngine
можно сказать (конечно, из другого потока, такого как ваш поток GUI), чтобы прервать выполнение:
QScriptEngine::abortEvaluation(const QScriptValue & result = QScriptValue())
Необязательный параметр используется как «псевдо-результат», который передается вызывающей стороне evaluate()
.
Вы должны либо установить флаг где-нибудь, либо использовать специальное значение результата в abortEvaluation()
чтобы подпрограмма вызывающего могла обнаружить, что выполнение было прервано.
Примечание: использование isEvaluating()
Вы можете увидеть, если оценка в настоящее время выполняется.