Название: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 16:07 Доброго времени суток. Вопрос может показаться простым\глупым\странным (нужное подчеркнуть), но я, прочитав несколько статей по поводу QThread, так и не совсем понял ответ на него.
Ситуация такая: есть главный поток - UI, у него есть объект класса cpu. В cpu настраиваются регистры, флаги, вбивается программа в память и потом она выполняется. Так вот, надо сделать, чтоб она (программа из памяти cpu) выполнялась в отдельном потоке, чтоб была возможность работать с UI (на случай, если в cpu программа с бесконечным циклом). При этом при все, при завершении выполнения программы из cpu, объект cpu не должен уничтожаться. Он должен ждать пока в него введут новую программу и запустят. Так вот вопрос в чем: достаточно ли для этого будет просто унаследовать класс cpu от QThread и метод run() перегрузить таким образом, чтоб в нем выполнялась программа, введенная в память процессора? При завершении программы (из памяти процессора) просто убивается процесс ее выполнения, а при повторном запуске программы он снова должен создаваться. Спасибо. Название: Re: Выполнение метода класса в новом потоке. Отправлено: OKTA от Апрель 09, 2014, 16:17 Можно, но так делать не рекомендуется и это крайне неудобно, если помимо простого выполнения код в созданном потоке должен обмениваться данными с другими объектами в других потоках. Проще сделать класс-обертку, в котором будет создаваться QThread и ваш cpu. Cpu при этом перемещается в созданный поток через movetothread и через класс-обертку с помощью сигналов обеспечиваются нужные взаимодействия. Я бы делал так :)
Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 16:27 если помимо простого выполнения код в созданном потоке должен обмениваться данными с другими объектами в других потоках. Сам cpu не обязательно кидать в новый поток, он может быть в одном потоке с UI, а вот метод execute() у cpu должен работать в новом потоке. В этом методе будут читаться данные из регистров и памяти cpu, и записываться данные в регистры и память. Получается, что все манипуляции с данными (на время выполнения программы из памяти cpu) будут выполняться в пределах объекта cpu. Хотя программа в память будет вводится из потока с UI.Проще сделать класс-обертку, в котором будет создаваться QThread и ваш cpu. Cpu при этом перемещается в созданный поток через movetothread и через класс-обертку с помощью сигналов обеспечиваются нужные взаимодействия. Я бы делал так :) А можно какой-нибудь простенький пример этого приема? Название: Re: Выполнение метода класса в новом потоке. Отправлено: OKTA от Апрель 09, 2014, 16:30 Если просто метод, то почитайте вот это :) http://qt-project.org/doc/qt-4.8/qtconcurrentrun.html
Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 16:42 Насколько я понял, чтоб использовать QtConcurrentRun, то у меня этот метод класса должен быть статическим?
А если использовать метод, который вы предложили ранее, то UI и cpu будут обмениваться данными через эту обертку, так? Название: Re: Выполнение метода класса в новом потоке. Отправлено: OKTA от Апрель 09, 2014, 16:43 Насколько я понял, чтоб использовать QtConcurrentRun, то у меня этот метод класса должен быть статическим? А если использовать метод, который вы предложили ранее, то UI и cpu будут обмениваться данными через эту обертку, так? Да нет, не должен он быть статическим. С чего вы взяли? Да, через обертку. Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 16:49 Ну, чтоб знать адрес функции на момент компиляции. По крайней мере, Win32Api функции CreateThread надо передавать статический метод класса.
Нашел на форуме тему с моей проблемой: http://www.prog.org.ru/topic_19310_0.html (http://www.prog.org.ru/topic_19310_0.html). Буду пробовать сделать таким же образом. Спасибо за помощь. Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 17:48 Сделал так. В UI вбиваю программу, которая будет в cpu выполняться в бесконечном цикле
Код: void MainWindow::on_start_cx_button_clicked() В cpu: Код: void intel8086::run() Однако программа зависает и падает на функции void intel8086::run(). Не подскажете, в чем может быть ошибка? Тут run выполняет бесконечный цикл и программа валится как только первая итерация проходит. Название: Re: Выполнение метода класса в новом потоке. Отправлено: gil9red от Апрель 09, 2014, 18:15 А что в step() происходит?
Название: Re: Выполнение метода класса в новом потоке. Отправлено: Old от Апрель 09, 2014, 18:26 Если посмотреть на код из on_start_cx_button_clicked, то наверное все таки так:
Код
Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 18:52 А что в step() происходит? Step - очень большая и сложная функция. По сути, моя программа - эмулятор микропроцессора. В нее вводится машинный код ассемблеровских команд и cpu их выполняет. В функции степ происходит расшифровка кода команды, определяются операнды и команда и выполняется команда в соответствии с полученным кодом.Если посмотреть на код из on_start_cx_button_clicked, то наверное все таки так: Вряд ли. Я просто в этом методе ввел команду в память процессора. Потом она будет вводится по другому, это я сейчас для теста так сделал.Код
Причем в консольном приложении эта программа (вбитая в cpu) отлично отрабатывает в бесконечном цикле. Название: Re: Выполнение метода класса в новом потоке. Отправлено: Old от Апрель 09, 2014, 18:58 Я не говорю, что это причина падения. Я просто уточнил, что при указанных вами исходных данных по адресу 0x10A уже не будет кода, а step будет вызван.
Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 19:01 Согласен, исправил. Спасибо. Но, к сожалению, это не решение проблемы.
Название: Re: Выполнение метода класса в новом потоке. Отправлено: Old от Апрель 09, 2014, 19:05 Но, к сожалению, это не решение проблемы. Скажите, я правильно понимаю, что так все будет работать в одном потоке?Код
Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 19:08 Да. В однопоточном консольном приложении это все отлично отрабатывает.
Ребят, понял в чем проблема. Проблема во взаимодействии с UI. Буду сейчас смотреть где проблема. Пока что вопрос есть, а как убить выполнение этой функции? Название: Re: Выполнение метода класса в новом потоке. Отправлено: Old от Апрель 09, 2014, 19:10 Да. В однопоточном консольном приложении это все отлично отрабатывает. А после запуска execute в отдельном потоке, в главном потоке происходит работа с объектом _cpu?Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 19:25 Да. Там тяжелое взаимодействие. Собственно, из-за этого и валилась программа.
У меня эта программа (вбитая в память cpu) в бесконечном цикле читает состояние чекбокса и выводит его в QLabel. Чекбокс "соединен" с адресом 0xfffa памяти cpu. Когда чекбокс помечен, по этому адресу пишется единица, когда не помечен - ноль. Аналогичным образом label "соединен" по адресу 0xfffb. Программа из памяти процессора в бесконечном цикле читает то, что по адресу 0xfffa и кидает по адресу 0xfffb. QLabel динамически создан в cpu и отображен на форме. При записи по адресу 0xfffb этот QLabel обновляется и изменение должно отобразиться на форме. Вот на моменте, когда я пытаюсь изменить этот label программа и валиться Название: Re: Выполнение метода класса в новом потоке. Отправлено: Old от Апрель 09, 2014, 19:29 Вот на моменте, когда я пытаюсь изменить этот label программа и валиться Ну так нельзя работать с GUI из другого потока. Или работайте в главном потоке или развязывайте взаимодействие через очередь событий, например, сигналами.Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 19:56 Ребят, всем спасибо. Вроде разобрался.
Теперь вопрос, как убить выполнение этой функции? Название: Re: Выполнение метода класса в новом потоке. Отправлено: Old от Апрель 09, 2014, 20:00 Теперь вопрос, как убить выполнение этой функции? Как всегда. :)Добавьте в вашу функцию проверку некоего флага и при его изменении выходите из функции. Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 21:27 QtConcurrent::run возвращает объект QFuture, у него есть метод cancel, который, вроде как, убивает поток, в котором выполняется этот метод. Его можно использовать, чтоб убить функцию или только флажком каким-нибудь?
Название: Re: Выполнение метода класса в новом потоке. Отправлено: Old от Апрель 09, 2014, 21:29 QtConcurrent::run возвращает объект QFuture, у него есть метод cancel, который, вроде как, убивает поток, в котором выполняется этот метод. Его можно использовать, чтоб убить функцию или только флажком каким-нибудь? Убивать нитки чревато, лучше их завершать.Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 21:43 Так а как завершить, если программа в процессоре работает в бесконечном цикле? И флаг тоже никакой нельзя проверить, так как программа (выполняемая cpu) пишется пользователем и заставлять его делать проверку флажка по какому-то адресу - не вариант совсем.
Название: Re: Выполнение метода класса в новом потоке. Отправлено: Old от Апрель 09, 2014, 21:48 Так а как завершить, если программа в процессоре работает в бесконечном цикле? И флаг тоже никакой нельзя проверить, так как программа (выполняемая cpu) пишется пользователем и заставлять его делать проверку флажка по какому-то адресу - не вариант совсем. Пользователя просить не надо. :)Вот на примере вашего кода: Код
Как только нужно завершить функцию execute, выполняемую в отдельном потоке, вызываете _cpu.stop() Название: Re: Выполнение метода класса в новом потоке. Отправлено: rudolfninja от Апрель 09, 2014, 21:50 Ну да, спасибо. Это, действительно, хороший вариант.
Спасибо, большое, всем, кто ответил. Проблему свою решил. |