Russian Qt Forum
Сентябрь 30, 2024, 18:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Запуск QtScript в отдельном потоке  (Прочитано 3536 раз)
tzeentch16
Гость
« : Октябрь 21, 2012, 16:32 »

Передо мной возникла такая задача: написать простой GUI редактор/интерпретатор сценариев языка, основаного на QtScript.

Проблема: невозможно прервать исполнение зависнувшего скрипта при помощи QScriptEngine::abortEvaluation(), так как GUI зависает.

Решение: запихнуть исполнение в отдельный поток.

Я никогда не писал многопоточные приложения, но делать нечего - начал кодить. Проблема в том, что я использую не QScriptEngine, а класс, унаследованный от него, но довольно криво написаный другим человеком. Кривость заключается в том, что должен быть только один экземпляр этого класса, и его нельзя копировать - иначе возникнут проблемы.

Итак, я написал простенький пример, в котором я создаю поток, передаю в него указатель на некий dummy-класс EnginePlaceHolder, затем запускаю поток. Есть GUI для запуска и остановки потока - все отлично работает.

Я обрадовался, но при попытке использовать вместо EnginePlaceHolder реальный ScriptEngine получаю тонну сообщений об ошибках от Qt:

QApplication: Object event filter cannot be in a different thread.
QObject::startTimer: timers cannot be started from another thread
QApplication: Object event filter cannot be in a different thread.
QObject::startTimer: timers cannot be started from another thread
...

Скажите, никто никогда не сталкивался с задачей запустить QtScript в отдельном потоке? Как это можно сделать, если обьект движка нельзя копировать? Как можно безопасно передать обьект движка в поток выполнения (не копируя его), и выполнить сценарий в отдельном потоке, так, чтобы при этом GUI не зависал, и можно было бы прервать исполнение? Возможно, кто-то где-то что-то читал об этом, я 3 дня по интернету лазил, ничего не нашел, но вдруг... Зараннее спасибо.
Записан
mutineer
Гость
« Ответ #1 : Октябрь 21, 2012, 19:51 »

Покажи код своего примера, может видно будет где ты ошибся
Записан
tzeentch16
Гость
« Ответ #2 : Октябрь 21, 2012, 20:30 »

Вот исходники примера: thread-test.rar. В нем ошибок нет, однако попытка использовать QScriptEngine вместо класса-путышки EnginePlaceHolder порождает большое количество сообщений об ошибках в консоли, потом программа зависает или падает.
« Последнее редактирование: Октябрь 21, 2012, 20:34 от tzeentch16 » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Октябрь 22, 2012, 09:20 »

но довольно криво написаный другим человеком. Кривость заключается в том, что должен быть только один экземпляр этого класса, и его нельзя копировать - иначе возникнут проблемы.
Не уверен что это кривость, вообще чужую корову охаять легко  Улыбающийся

Не смотрел выложенный код, но первое что бросается в глаза - сделать moveToThread всем классам которые планируются в отдельной нитке. Поскольку moveToThread автоматычно срабатывает для чилдренов, вызовов потребуется немного. Судя по исходникам abortEvaluation() может быть вызван из главной нитки для прерывания
 
Записан
mutineer
Гость
« Ответ #4 : Октябрь 22, 2012, 10:30 »

Igors прав - ты не делаешь moveToThread и _engine продолжает жить там же, где и был создан - в главном треде
Записан
tzeentch16
Гость
« Ответ #5 : Октябрь 22, 2012, 16:15 »

Да, с moveToThread() все работает, спасибо вам большое.

Я сперва мало что про нее нашел, решил - она мне не поможет, а сейчас погуглил специально про нее, попался неплохой пример, теперь работает.
« Последнее редактирование: Октябрь 22, 2012, 16:17 от tzeentch16 » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.136 секунд. Запросов: 22.