Название: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 28, 2009, 18:48 Всем хай!
Есть необходимость, в потоке, создавать GUI объекты. Но программа вываливается с сообщением типа сяго: (http://pic.ipicture.ru/uploads/091128/1W52NQo15w.png) (http://ipicture.ru/) Кто-то сталкивался с подобной нуждой? Ну вот позарез нужно создавать объекты в потоке. Вот :) Название: Re: Создание/вызов методов в разных потоках. Отправлено: lit-uriy от Ноябрь 28, 2009, 18:58 GUI можно создавать только в главном потоке. И нужды создавать их в другом потоке, все таки нету.
Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 28, 2009, 19:01 Юра, а мне нужно. И это не баловство/игрушки, реальная задача.
Хочу в цикле, создавать объекты типа QWebView. Чтоб страницы вебовские загружать, с поддержкой ява-скрипт. Как это реализовать? Название: Re: Создание/вызов методов в разных потоках. Отправлено: serg_hd от Ноябрь 28, 2009, 19:08 GUI можно создавать только в главном потоке. И нужды создавать их в другом потоке, все таки нету. У меня похожая трабла. Нужно использовать QWebView (или QWebPage), загружать в него QUrl - и так во многих параллельных потоках для написания веб-сёрфера. Какие тут ещё альтернативы кроме многопоточности?Я использую QT Jambi (java-фреймворк над QT), объекты QWebView и QUrl в отдельном потоке создаются (в отличие от сишного qt) и можно легко оперировать их методами, за исключением QWebView.load(QUrl), где выдаёт: Код: QObject: Cannot create children for a parent that is in a different thread. Название: Re: Создание/вызов методов в разных потоках. Отправлено: pastor от Ноябрь 28, 2009, 19:48 Юра, а мне нужно. Нельзя и точка! В ассистанте все написано. Даже в сообщении об ошибке об этом идет речь. Название: Re: Создание/вызов методов в разных потоках. Отправлено: BRE от Ноябрь 28, 2009, 19:53 Как это реализовать? Можно попробовать сам QWebView создавать в главном потоке, а в дочерних потоках работать с объектами классов QWebPage/QWebFrame.Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 28, 2009, 19:57 Юра, а мне нужно. Нельзя и точка! В ассистанте все написано. Даже в сообщении об ошибке об этом идет речь. Где можно почитать внятные разъяснения? В сообщении об ошибке, сообщается ошибка, а не причина невозможности создания ГУИ объектов в потоке. Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 28, 2009, 19:59 Юра, а мне нужно. Нельзя и точка! В ассистанте все написано. Даже в сообщении об ошибке об этом идет речь. Где можно почитать внятные разъяснения? В сообщении об ошибке, сообщается ошибка, а не причина невозможности создания ГУИ объектов в потоке. Ну если нельзя, то что тут сделаешь! Я думаю что QWebView для загрузки сам создает поток в котором и грузит данные. А создавать QWebView можно отправляя сигнал из второстепенного потока объекту в главном потоке, который его и создаст, так что это не проблема Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 28, 2009, 20:06 Цитировать создавать QWebView можно отправляя сигнал из второстепенного потока объекту в главном потоке, который его и создаст Т.е. в основном потоке, создать слот, который будет создавать QWebView, и испускать сигнал с аргументом типа QWebView*, обратно в поток? А вас правильно понял?Кажется это реально выполнимая задача ;) Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 28, 2009, 20:25 Цитировать создавать QWebView можно отправляя сигнал из второстепенного потока объекту в главном потоке, который его и создаст Т.е. в основном потоке, создать слот, который будет создавать QWebView, и испускать сигнал с аргументом типа QWebView*, обратно в поток? А вас правильно понял?Кажется это реально выполнимая задача ;) Да. А можно и поизвращаться. У меня была задачка: При длительной обработке данных(исталляция пакаджа) в другом потоке в определенных случаях создавать дополнительные виджеты. Причем это было в некотором объекте который ничего не знает про то, в каком потоке работает и не должен знать! Мало того создание виджетов делалось где-то в цикле и соответственно даже если бы объект и знал про поток, то сделать посылку и получение сигнала было бы тяжело и сильно все портило бы. Так что я сделал синхронизирующий вызов метода унаследовав свой QApplication и QThread. Если интересно, посмотри тему: http://www.prog.org.ru/index.php?topic=10041.msg59182#msg59182 (http://www.prog.org.ru/index.php?topic=10041.msg59182#msg59182) Название: Re: Создание/вызов методов в разных потоках. Отправлено: Igors от Ноябрь 28, 2009, 20:36 Юра, а мне нужно. Нельзя и точка! В ассистанте все написано. Даже в сообщении об ошибке об этом идет речь. Так что это не вина Qt Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 28, 2009, 20:38 Spectre
Огромное спасибо! По идее это то, что нужно. Но один вопрос остается без ответа: Почему ГУИ объекты нельзя создавать в потоке? Где об этом можно почитать? Может какой костыль написать? ;D п.с. эх...Константина бы сюда... Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 28, 2009, 20:40 Цитировать если просматривать те же ф-ции базовой графики/рисования то легко можно натолкнуться на "not thread-safe" Да, согласен. Но если объекту не указывать parent/paint_device, то он и рисоваться не будет. Что в этом случае мешает?Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 28, 2009, 20:55 Spectre Огромное спасибо! По идее это то, что нужно. Но один вопрос остается без ответа: Почему ГУИ объекты нельзя создавать в потоке? Где об этом можно почитать? Может какой костыль написать? ;D п.с. эх...Константина бы сюда... Написано в ассистанте, где точно не помню. Почему, никогда специально не разбирался, но в C++ Builder, точно так же. Вот костыль и написал. :) Если будешь юзать причитай тему до конца, там есть правки. Там есть еще define для простого вызова viod методов для this: MyClass::anyMethod(....) { ... // вместо // this->methodforsync(); // вызываем sb_synchronize_method(MyClass, methodforsync); ... } MyClass::methodforsync(void) { ... ... } Название: Re: Создание/вызов методов в разных потоках. Отправлено: Igors от Ноябрь 28, 2009, 20:56 Цитировать если просматривать те же ф-ции базовой графики/рисования то легко можно натолкнуться на "not thread-safe" Да, согласен. Но если объекту не указывать parent/paint_device, то он и рисоваться не будет. Что в этом случае мешает?И вообще, нечего распускать пользователя обилием возможностей, он это не ценит. Не так уж давно ВСЕ обращения к ОС возможны были только в главной нитке - и ничего, работали. Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 28, 2009, 21:08 Spectre
Спасибо. Изучаю вашу тему по ссылке. Igors Вынужден согласиться. Так как написание правильного алгоритма, займет меньше времени чем ковыряние поднаготной Qt ;) Название: Re: Создание/вызов методов в разных потоках. Отправлено: BRE от Ноябрь 28, 2009, 22:38 Так как написание правильного алгоритма, займет меньше времени чем ковыряние поднаготной Qt ;) Да это скорее не ограничение Qt, а ограничение любого графического интерфейса.Экран - это ресурс, доступ к которому должен быть синхронным. Если один поток начнет перерисовывать виджет и на середине будет прерван, управление получит другой поток, который также захочет перерисовать другой виджет на экран, а эти виджеты перекрывают друг друга, то проблемы неизбежны. Также при сложных интерфейсах (в которых виджеты могут перекрывать друг друга) необходима оптимизация обновляемых регионов. Например, перерисовывается виджет нижнего уровня, который на 90% перекрыт виджетами верхнего уровня, то целесообразно перерисовывать только видимую часть (10%) этого виждета. Такая оптимизация возможна только если рисование всего происходит в одном месте (главном потоке, например). Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 28, 2009, 23:29 Так как написание правильного алгоритма, займет меньше времени чем ковыряние поднаготной Qt ;) Да это скорее не ограничение Qt, а ограничение любого графического интерфейса.Пункт 1 Экран - это ресурс, доступ к которому должен быть синхронным. Если один поток начнет перерисовывать виджет и на середине будет прерван, управление получит другой поток, который также захочет перерисовать другой виджет на экран, а эти виджеты перекрывают друг друга, то проблемы неизбежны. Пункт 2 Также при сложных интерфейсах (в которых виджеты могут перекрывать друг друга) необходима оптимизация обновляемых регионов. Например, перерисовывается виджет нижнего уровня, который на 90% перекрыт виджетами верхнего уровня, то целесообразно перерисовывать только видимую часть (10%) этого виждета. Такая оптимизация возможна только если рисование всего происходит в одном месте (главном потоке, например). Не согласен Пункт 1 Это обеспечивается операционкой, поскольку существует множество GUI процессов. И если бы это было так как ты написал, то проблема была бы на уровне главных потоков этих процессов. Пункт 2 Примем: Виджеты 1-го уровеня виджеты не прекрываемые другими виджетами и не содежащие другие виджеты Виджеты 2-го уровня - могут содержать только виджеты 1-го уровеня или быть ими пререкрыты Итд.. 1 вариант) Пререрисовка в главном потоке. Имеем виджет 2 уровня который перересовываем, соответственно виджеты 1-го уровня пресекающиеся с ним - будут ли они перерисовываться? - НЕТ. Прересовываятся только видимые регионы. 2 вариант) Пререрисовка в разных потоках. Все тоже самое как и в пункте 1. Разница только в том что для получения регионов виджета(их несколько из-за перекрытий) требующих перерисовки может потребоваться Mutex Предположим имеем виджет 2 уровня Название: Re: Создание/вызов методов в разных потоках. Отправлено: BRE от Ноябрь 28, 2009, 23:38 Пункт 1 Что обеспечивается операционкой?Это обеспечивается операционкой, поскольку существует множество GUI процессов. И если бы это было так как ты написал, то проблема была бы на уровне главных потоков этих процессов. В Qt операционка управляет только виджетами верхнего уровня. Все внутренние отрисовки производит сама Qt. Но не суть важно. Операционка точно также перехватывает события PAINT и сама определяет момент перерисовки на экран. И делает она это в один момент для всех окон всех приложений. Название: Re: Создание/вызов методов в разных потоках. Отправлено: lit-uriy от Ноябрь 28, 2009, 23:45 Есть такие страшные слова:
Потокобезопасность реентерабельность Есть достаточно много людей которые с этими понятиями парятся и до конца их не понимают (я один из них). Дак вот если ещё QWidget'ы сделать со всякой там реентерабельностью, то телефон службы техподдержки трольтеха отключила бы телефонная компания. В Асистенте сказано: Цитировать Несмотря на то, что QObject реентерабелен, классы ГПИ, особенно QWidget и все его подклассы, таковыми не являются. Они могут использоваться только из главного потока. тыц (http://www.doc.crossplatform.ru/qt/4.4.3/threads.html#qobject-reentrancy)... На практике невозможно использовать классы ГПИ в других потоках, кроме главного, но выполнение продолжительных действий можно легко поместить в отдельный поток и отображать на экране результаты выполнения средствами главного потока по окончании обработки во вспомогательном потоке. Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 28, 2009, 23:47 Пункт 1 Что обеспечивается операционкой?Это обеспечивается операционкой, поскольку существует множество GUI процессов. И если бы это было так как ты написал, то проблема была бы на уровне главных потоков этих процессов. В Qt операционка управляет только виджетами верхнего уровня. Все внутренние отрисовки производит сама Qt. Но не суть важно. Операционка точно также перехватывает события PAINT и сама определяет момент перерисовки на экран. И делает она это в один момент для всех окон всех приложений. Ну а где противоречие с тем что я написал выше? Ты говорил что это не проблема библиотек и привел аргументы, я привел тебе примеры. Не спорю, вполне вожможно что операционка делает перерисовку окон синхронно(синхронизированно) для разных процессов(их главных потоков) и это пример того что это возможно! => ничто не мешает сделать необходимую синхронизацию при отрисовки виджетов на уровне библиотеки! Название: Re: Создание/вызов методов в разных потоках. Отправлено: lit-uriy от Ноябрь 28, 2009, 23:48 там же, по ссылке, указаны и причины
Название: Re: Создание/вызов методов в разных потоках. Отправлено: BRE от Ноябрь 28, 2009, 23:53 ничто не мешает сделать необходимую синхронизацию при отрисовки виджетов на уровне библиотеки! Да сделать то все можно, только для чего, в чем будет выигрыш? Если все сведется к одному потоку, который и будет все отрисовывать.Что даст эта возможность, кроме усложнения (и наверняка) замедлению библиотеки? Наверное, поэтому это и не было сделано. Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 00:11 там же, по ссылке, указаны и причины Абсолютно не связанные вещи, речь шла о проблемах пререисовки и что якобы это не ограничения библиотеки, с чем я не согласен! На мой взгляд это именно ограничения библиотеки. Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 00:15 ничто не мешает сделать необходимую синхронизацию при отрисовки виджетов на уровне библиотеки! Да сделать то все можно, только для чего, в чем будет выигрыш? Если все сведется к одному потоку, который и будет все отрисовывать.Что даст эта возможность, кроме усложнения (и наверняка) замедлению библиотеки? Наверное, поэтому это и не было сделано. Мы говорили именно о перерисовке. Выигрыш в том что удобнее использовать, я поскольку перерисовка делается, относительно медленно, то thread-save (через Mutex) не даст замедления. Название: Re: Создание/вызов методов в разных потоках. Отправлено: BRE от Ноябрь 29, 2009, 00:21 На мой взгляд это именно ограничения библиотеки. Давай посмотрим на несколько моментов. Например:В одном потоке (1) создается окно, в другом потоке (2) создается виджет, который должен располагаться на этом окне. На примере Qt, parent'ом для этого виджета нужно указать окно из потока 1. Поток 2 начинает что-то делать со своим виджетом, в середине работы происходит переключение на поток 1, который решает разрушить окно. Что делать библиотеке? Убить виджет вместе с окном, но тогда при переключении на поток 2 (где идет работа с этим виджетом) все ляжет. Отвязать этот виджет и не трогать, тогда кто будет удалять виджет и что с ним вообще дальше делать? Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 00:42 Есть такие страшные слова: По поводу реентерабельности, вот почитай:Потокобезопасность реентерабельность Есть достаточно много людей которые с этими понятиями парятся и до конца их не понимают (я один из них). Реентерабельность (http://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B5%D0%BD%D1%82%D0%B5%D1%80%D0%B0%D0%B1%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D1%8C) Короче это thread-save "Реентерабельность" для функций. Для объекта thread-save: - Все методы - реентерабельны - нет непосредственного(не через методы) доступа к данным объекта Вроде так Дак вот если ещё QWidget'ы сделать со всякой там реентерабельностью, то телефон службы техподдержки трольтеха отключила бы телефонная компания. В Асистенте сказано: Цитировать Несмотря на то, что QObject реентерабелен, классы ГПИ, особенно QWidget и все его подклассы, таковыми не являются. Они могут использоваться только из главного потока. тыц (http://www.doc.crossplatform.ru/qt/4.4.3/threads.html#qobject-reentrancy)... На практике невозможно использовать классы ГПИ в других потоках, кроме главного, но выполнение продолжительных действий можно легко поместить в отдельный поток и отображать на экране результаты выполнения средствами главного потока по окончании обработки во вспомогательном потоке. Это связано не только с виджетами, но и с кучей других классов. Я и не спорил о том что виджеты нельзя использовать многопоточно и не в главном потоке. И это естественно касается не только создания но и любого использования виджетов(вызова их методов) за пределами главного потока. Но не понятны причины почему это так. Не thread-save предполагает использование объекта только в одном потоке, но это не занчит что в главном! Про поблемы синхронизации перерисовки я уже писал - это проблема библиотеки. неужели проблема только в этом? ==== Дока QT - это нечто! Я не верю что накосячили в переводе. Постоянно встречаю такие приколы! Цитировать * Потомок QObject должен всегда создаваться в том же потоке, что и предок. Это как понимать! Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 00:56 На мой взгляд это именно ограничения библиотеки. Давай посмотрим на несколько моментов. Например:В одном потоке (1) создается окно, в другом потоке (2) создается виджет, который должен располагаться на этом окне. На примере Qt, parent'ом для этого виджета нужно указать окно из потока 1. Поток 2 начинает что-то делать со своим виджетом, в середине работы происходит переключение на поток 1, который решает разрушить окно. Что делать библиотеке? Убить виджет вместе с окном, но тогда при переключении на поток 2 (где идет работа с этим виджетом) все ляжет. Отвязать этот виджет и не трогать, тогда кто будет удалять виджет и что с ним вообще дальше делать? Это проблема неправильного использования, неправильной сихронизации, т.е. проблема программиста. С таким же успехом можно напортачить с любым объектом совместно используемым в нескольких потоках. Название: Re: Создание/вызов методов в разных потоках. Отправлено: Igors от Ноябрь 29, 2009, 01:38 Но не понятны причины почему это так. Не thread-save предполагает использование объекта только в одном потоке, но это не занчит что в главном! Про поблемы синхронизации перерисовки я уже писал - это проблема библиотеки. неужели проблема только в этом? Библиотека здесь ни при чем. Представим себе что сейчас OS заполняет/заливает регион каким-то цветом (шлет 5-10Mb в видео). Понятно что если кто-то встрянет с др. рисованием - регион разрушен, crash. Значит надо как-то "держать и не пущать" остальных рисующих. А каким образом если 2 и более ниткам разрешено захватывать контекст, выкладывать окна и.т.п? Все хорошо если несколько процессов рисуют "одновременно" (якобы). OS все равно делает это последовательно (на слабом железе хорошо видно) - сначала пошлет paint/update одному окну/процессу, потом другому (а между этим проверит др. события). А вот если 2 нитки в 1 процессе прутся - как? Ставить мутекс на каждый чих? Не хуже меня знаете - удовольствие слишком дорогое для операций рисования.==== Да так и понимать: они крутят EventLoop для каждой нитки. А обработчик объекта обычно делает "что-то сверху" и отдается на обработчик парента - а событие-то было послано в другом loop. Лучше сначала разобраться а потом горячиться :)Дока QT - это нечто! Я не верю что накосячили в переводе. Постоянно встречаю такие приколы! Цитировать * Потомок QObject должен всегда создаваться в том же потоке, что и предок. Это как понимать! Название: Re: Создание/вызов методов в разных потоках. Отправлено: Павел_F. от Ноябрь 29, 2009, 01:59 Вот вы тут спорите про потоки... И ГУЙ в разных потоках... Я вот обдумал все, представил себя пользователем и пришел к выводу что я не могу смотреть в два разных ГУЯ одновременно. Только по очереди. А раз пользователь не может то зачем это реализовывать программисту? Тем более что это сложно реализовать. Ведь любая программа рассчитана на некоего пользователя. И я считаю это весьма логичным, даже не вдаваясь в потокобезопасность и прочее( хоть и имею представление об этом). Так что один пользователь смотрит в один ГУЙ, а что и когда появится в этом ГУЕ это уже дело программиста. И если у последнего возникает надобность в двух ГУЯх одновременно то что-то он напутал в разработке интерфейса.
Название: Re: Создание/вызов методов в разных потоках. Отправлено: zenden от Ноябрь 29, 2009, 02:10 Цитата: Павел_F Я вот обдумал все, представил себя пользователем и пришел к выводу что я не могу смотреть в два разных ГУЯ одновременно. Вы сначала ознакомились лучше бы ознакомились с сутью вопроса, прежде чем выдавать такие перлы. Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 02:13 Вот вы тут спорите про потоки... И ГУЙ в разных потоках... Я вот обдумал все, представил себя пользователем и пришел к выводу что я не могу смотреть в два разных ГУЯ одновременно. Только по очереди. А раз пользователь не может то зачем это реализовывать программисту? Тем более что это сложно реализовать. Ведь любая программа рассчитана на некоего пользователя. И я считаю это весьма логичным, даже не вдаваясь в потокобезопасность и прочее( хоть и имею представление об этом). Так что один пользователь смотрит в один ГУЙ, а что и когда появится в этом ГУЕ это уже дело программиста. И если у последнего возникает надобность в двух ГУЯх одновременно то что-то он напутал в разработке интерфейса. Ты хоть сам понял что написал. Название: Re: Создание/вызов методов в разных потоках. Отправлено: Павел_F. от Ноябрь 29, 2009, 02:22 Понял, может не верно изложил. Во всей теме спорят про "теорию вопроса". Практического же увидел только "QWebView в цикле", инет браузер и намек на надобность показать окошко по событию из другого потока. Во всех этих задачах я не вижу смысла делать графический интерфейс в нескольких потоках. А зечем спорить почему этого нет и придумывать как это сделать если это не надо?
Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 02:59 Но не понятны причины почему это так. Не thread-save предполагает использование объекта только в одном потоке, но это не занчит что в главном! Про поблемы синхронизации перерисовки я уже писал - это проблема библиотеки. неужели проблема только в этом? Библиотека здесь ни при чем. Представим себе что сейчас OS заполняет/заливает регион каким-то цветом (шлет 5-10Mb в видео). Понятно что если кто-то встрянет с др. рисованием - регион разрушен, crash. Значит надо как-то "держать и не пущать" остальных рисующих. А каким образом если 2 и более ниткам разрешено захватывать контекст, выкладывать окна и.т.п? Все хорошо если несколько процессов рисуют "одновременно" (якобы). OS все равно делает это последовательно (на слабом железе хорошо видно) - сначала пошлет paint/update одному окну/процессу, потом другому (а между этим проверит др. события). А вот если 2 нитки в 1 процессе прутся - как? Ставить мутекс на каждый чих? Не хуже меня знаете - удовольствие слишком дорогое для операций рисования.- Поскольку в OS одновременно работают много процессов, в том числе и имеющих графический интерфейс, то на уровне OS такой проблемы нет. Система сама устанавливает блокировки при обращении к ее определенным ресурсам, в том числе и к графическим контекстам! Так что проблема только на уровне библиотеки. - По поводу накладности Mutex , для данного случая - абсолютно не согласен. Не тот случай! a) Операция прерисовки относительно редкая. b) Очень длительная операция по сравнению со временем создания блокировки - отношение много порядков И к слову. Реализация Mutex в QT сделана не хорошо. Нормальный Mutex предполагает Spin Count(покрутиться заданное колличество раз 1000-100000 на атомарной операции в ожидании разблокировки прежде чем усыпить поток)! Таким образом, QT-й Mutex не позволяет без больших накладных расходов использовать его для межпоточной защиты очень частых, но очень коротких по времени последовательностей операций. ==== Да так и понимать: они крутят EventLoop для каждой нитки. А обработчик объекта обычно делает "что-то сверху" и отдается на обработчик парента - а событие-то было послано в другом loop. Лучше сначала разобраться а потом горячиться :)Дока QT - это нечто! Я не верю что накосячили в переводе. Постоянно встречаю такие приколы! Цитировать * Потомок QObject должен всегда создаваться в том же потоке, что и предок. Это как понимать! Перечитал в оригинале, понял прикол. Речь об отношении включения(родитель-дочерний объект), а не о наследовании. :) Цитировать The child of a QObject must always be created in the thread where the parent was created. Название: Re: Создание/вызов методов в разных потоках. Отправлено: lit-uriy от Ноябрь 29, 2009, 03:13 >>а не о наследовании
да, надо будет поправить, "потомка" на "дочерний", а "предка" на "родительский". В новых переводах так и договорились делать. А то двояко звучит Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 03:14 Понял, может не верно изложил. Во всей теме спорят про "теорию вопроса". Практического же увидел только "QWebView в цикле", инет браузер и намек на надобность показать окошко по событию из другого потока. Во всех этих задачах я не вижу смысла делать графический интерфейс в нескольких потоках. А зечем спорить почему этого нет и придумывать как это сделать если это не надо? Пример с тем же QWebView, насколько я понял он грузит данные в другом потоке. Но вот отрисовку он делает естественно в главном. И я заметил(я это протестировал), если ему подать что-то очень тяжелое для отображения, то он замораживает интерфейс на некоторое время. Сам ощутил замараживание секунд на 5! Очень неприятно. А вот если бы можно было рисовать в другом потоке, то этого бы не происходило Название: Re: Создание/вызов методов в разных потоках. Отправлено: lit-uriy от Ноябрь 29, 2009, 03:16 >>если бы можно было рисовать в другом потоке, то этого бы не происходило
рисовать можно в другом потоке, рисуй на QImage, а в главном копируй его. Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 03:26 >>если бы можно было рисовать в другом потоке, то этого бы не происходило рисовать можно в другом потоке, рисуй на QImage, а в главном копируй его. Ты уверен? Вроде painter это не позволяет??? Даже если это так, то ты не заставишь это делать тот-же QWebView! Название: Re: Создание/вызов методов в разных потоках. Отправлено: Igors от Ноябрь 29, 2009, 03:38 - Поскольку в OS одновременно работают много процессов, в том числе и имеющих графический интерфейс, то на уровне OS такой проблемы нет. Система сама устанавливает блокировки при обращении к ее определенным ресурсам, в том числе и к графическим контекстам! Так что проблема только на уровне библиотеки. Не путайте, OS никакой защиты не имеет, попробуйте painter.begin() без painter.end() или создавать QPainter не на стеке - и получите неприятности очень быстро. Для многих процессов OS просто проталкивает их последовательно но это не прокатит с 2 и более нитками 1 процесса.Название: Re: Создание/вызов методов в разных потоках. Отправлено: pastor от Ноябрь 29, 2009, 05:28 Но один вопрос остается без ответа: Почему ГУИ объекты нельзя создавать в потоке? Где об этом можно почитать? Может какой костыль написать? ;D имхо, это ограничение библиотеки и никакой костыль ненапишешь. Нестоит забывать, что Qt это кросплатформенный фреймворк, и, возможно, не все ОС поддерживают несколько GUI потоков в пределах процесса. Например, винда поддерживает несколько GUI потоков. По потокам и процессам можно почитать в очень неплохой книге: Джеффри Рихтер. Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows а именно главы 6, 26, 27. Название: Re: Создание/вызов методов в разных потоках. Отправлено: pastor от Ноябрь 29, 2009, 05:35 Короче это thread-save "Реентерабельность" для функций. Для объекта thread-save: - Все методы - реентерабельны - нет непосредственного(не через методы) доступа к данным объекта Вроде так Нитак. thread-save != reentrant Функции, которые можно одновременно вызывать из разных потоков - tread safe. Если в классе все функции такие, то и класс называется tread safe. reentrant - функции, которые можно безопастно вызывать для одного и того же екземпляра класса только из одного потока - в котором он был создан. Подробнее читаем в ассистанте - Thread Support in Qt Название: Re: Создание/вызов методов в разных потоках. Отправлено: lit-uriy от Ноябрь 29, 2009, 05:38 >>Ты уверен? Вроде painter это не позволяет???
для QImage можно, он специально создан для использования в разных потоках Название: Re: Создание/вызов методов в разных потоках. Отправлено: pastor от Ноябрь 29, 2009, 05:43 Ты уверен? Вроде painter это не позволяет??? QImage Class Reference Цитировать Because QImage is a QPaintDevice subclass, QPainter can be used to draw directly onto images. When using QPainter on a QImage, the painting can be performed in another thread than the current GUI thread. The Paint System Цитировать One advantage of using QImage as a paint device is that it is possible to guarantee the pixel exactness of any drawing operation in a platform-independent way. Another benefit is that the painting can be performed in another thread than the current GUI thread. Иногда полезно заглядывать в ассистант. Название: Re: Создание/вызов методов в разных потоках. Отправлено: serg_hd от Ноябрь 29, 2009, 14:09 Вот вы тут спорите про потоки... И ГУЙ в разных потоках... Я вот обдумал все, представил себя пользователем и пришел к выводу что я не могу смотреть в два разных ГУЯ одновременно. Только по очереди. Дело в том, что изначально речь шла не столько о ГУЕ, сколько о qwebview в частности. Задача (например в моём случае) состоит в том, чтобы эмитировать работу "нескольких браузеров" одновременно, вот и всё. Выводить на экран ничего не нужно, главное чтобы была прорисовка js, html, css, etc. "за кулисами". Т.е. тут, несмотря на то, что метод загрузки url'a load() асинхронный - этого мало. Будут "переходы" на другие сайты, поиск текста по страницам, все эти методы асинхронными не будут, чтобы делать всё в одном потоке. Тут уже был дан вариант решения - слать сигнал на главный поток, чтобы он создал экземпляр qwebview и возвращал его назад в поток. Тут у меня один вопрос (наверное, ввиду моей неопытности при работе с сигналами/слотами): как указать слот, чтобы сигнал типа qwebview слался в run() дочернего потока?? Пробовал как вариант: Код: class RunThreads extends QSignalEmitter implements Runnable п.с. сил больше нет бороться с этим qwebview(( Название: Re: Создание/вызов методов в разных потоках. Отправлено: BRE от Ноябрь 29, 2009, 14:30 п.с. сил больше нет бороться с этим qwebview(( Я это уже предлагал, но повторюсь.А ты не пробовал использовать вместо QWebView объекты классов QWebPage/QWebFrame. Это не GUI-классы и думаю спокойно смогут работать в других потоках. Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 14:33 Тут у меня один вопрос (наверное, ввиду моей неопытности при работе с сигналами/слотами): как указать слот, чтобы сигнал типа qwebview слался в run() дочернего потока?? Смотри: int QThread::exec (); Название: Re: Создание/вызов методов в разных потоках. Отправлено: serg_hd от Ноябрь 29, 2009, 14:34 п.с. сил больше нет бороться с этим qwebview(( Я это уже предлагал, но повторюсь.А ты не пробовал использовать вместо QWebView объекты классов QWebPage/QWebFrame. Это не GUI-классы и думаю спокойно смогут работать в других потоках. Название: Re: Создание/вызов методов в разных потоках. Отправлено: BRE от Ноябрь 29, 2009, 14:34 У QWebPage нет метода load() А у QWebFrame есть. :)Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 14:38 QWebFrame * QWebPage::currentFrame () const Предаем его в другой поток void QWebFrame::load ( const QUrl & url) Видимо так. Название: Re: Создание/вызов методов в разных потоках. Отправлено: zenden от Ноябрь 29, 2009, 14:49 Конкретную задачу решили, а общую - нет.
Название: Re: Создание/вызов методов в разных потоках. Отправлено: serg_hd от Ноябрь 29, 2009, 14:50 конкретную это какую?
Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 15:14 Цитировать this.wv.load(this.url); Так делать нельзя. ВебВью создан в одном потоке, ты вызываешь его метод из другого потока. Шли ему сигнал:Код Т.е. я это реализовал именно так. Один поток! Шлет сигналы на создание вьюшек, в слоте получает указатель на созданный объект. пихает его массив указателей. Еще поправка. Так как все созданные объекты конектятся к одному сигналу, то при его испускании, они все получают один УРЛ. А этого нам не нужно ;) Чтоб этого избежать, я унаследовался от QWebView, добавил метод load(QWidget*, const QUrl&). В этом методе я проверяю, этому ли объекту предназначается посланный сигнал. Да, это кривой костыль, знаю. Но нужно написать QSignalMapper, только наоборот. И еще в унаследованный класс добавил метод bool isFree() const. При получении СВОЕГО урл, этот флаг ставится в false. Когда же QWebView, заканчивает загрузку, этот флаг ставиться в true, и цикл, перебирающий объекты, видя что "этот" свободен, испускает сигнал. Все. Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 15:36 Полез во внутренности QWebView, и заблудился.
Одно что я понял, это то, что QWebView создает отдельный поток. Так как когда я закачиваю файл, прогресс операции обновляется без задержек, и обработчики всяких кнопок работают. Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 15:51 Цитировать this.wv.load(this.url); Так делать нельзя. ВебВью создан в одном потоке, ты вызываешь его метод из другого потока. Шли ему сигнал:Код Т.е. я это реализовал именно так. Один поток! Шлет сигналы на создание вьюшек, в слоте получает указатель на созданный объект. пихает его массив указателей. Еще поправка. Так как все созданные объекты конектятся к одному сигналу, то при его испускании, они все получают один УРЛ. А этого нам не нужно ;) Чтоб этого избежать, я унаследовался от QWebView, добавил метод load(QWidget*, const QUrl&). В этом методе я проверяю, этому ли объекту предназначается посланный сигнал. Да, это кривой костыль, знаю. Но нужно написать QSignalMapper, только наоборот. И еще в унаследованный класс добавил метод bool isFree() const. При получении СВОЕГО урл, этот флаг ставится в false. Когда же QWebView, заканчивает загрузку, этот флаг ставиться в true, и цикл, перебирающий объекты, видя что "этот" свободен, испускает сигнал. Все. Что к чему. Что-то намудрил. Я согласен что как я написал нельзя, но это общая схема. Чуть более подробно. В главном потоке: - QWebPage* WebPage = new QWebPage(NULL); - QWebFrame* WebFrame = WebPage->mainFrame(); - Cоздаем новый поток и передаем ему WebFrame или предаем каким либо образом(можно и через сигнал) WebFrame в уже существующий поток Во второстепенном потоке: - WebFrame::load (const QUrl & url) - Испускаем сигнал после загрузки В главном потоке: WebView->setPage(WebPage) ============ Остальное технические детали, главное чтобы WebFrame::load (const QUrl & url) делался в другом потоке. ============ Но есть проблема! Может этого и нельзя сделать! ??? WebPage - обязан создаваться в главном потоке, поскольку его родителем будет QWebView Цитировать The child of a QObject must always be created in the thread where the parent was created. Родителем WebFrame является WebPage, все нормально. Предаем его в другой поток, вызываем там WebFrame::load. И наш WebFrame при загрузке создает у себя дочерние QWebFrame !!! Что недопустимо, они должны быть созданы в главном потоке! Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 16:08 Цитировать Что к чему это вопрос?Цитировать Что-то намудрил Жду пояснений.Цитировать Я согласен что как я написал нельзя, но это общая схема так я не вас цитировал ;)Что-то вы намудрили ;) Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 16:17 Цитировать Что к чему это вопрос?Цитировать Что-то намудрил Жду пояснений.Цитировать Я согласен что как я написал нельзя, но это общая схема так я не вас цитировал ;)Что-то вы намудрили ;) Ты привел какой-то абсрактный код, неизвестно что делающий. Он не работоспосбен поскольку повыдерганы куски. По нему ничего понять нельзя. Привел примерно такое же объяснение. Вот я и написал - "Что к чему". Если уж хочешь рассказать и показать свой вариант, делай это так что бы было понятно не только тебе. :) Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 16:20 Цитировать Ты привел какой-то абсрактный код, неизвестно что делающий. Он не работоспосбен поскольку повыдерганы куски. По нему ничего понять нельзя. Привел примерно такое же объяснение. Вот я и написал - "Что к чему". Все нормально описал. Если не достаточно букав, вот, посмотрите: http://rghost.ru/655431Если уж хочешь рассказать и показать свой вариант, делай это так что бы было понятно не только тебе. Улыбающийся Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 16:39 Цитировать Ты привел какой-то абсрактный код, неизвестно что делающий. Он не работоспосбен поскольку повыдерганы куски. По нему ничего понять нельзя. Привел примерно такое же объяснение. Вот я и написал - "Что к чему". Все нормально описал. Если не достаточно букав, вот, посмотрите: http://rghost.ru/655431Если уж хочешь рассказать и показать свой вариант, делай это так что бы было понятно не только тебе. Улыбающийся Описал нормально для себя! Что ты там описал понимаешь только ты. Вообще даже не до конца понятно какую ты решал задачу, а без этого невозможно понять как ты ее решал. Цитировать Т.е. я это реализовал именно так. Что реализавал, опиши задачу. Мы много чего обсуждали в данной теме.Видео посмотрел. Чего-то там дергается и прыгает, весело так прыгает; :) Название: Re: Создание/вызов методов в разных потоках. Отправлено: serg_hd от Ноябрь 29, 2009, 16:42 niXman, в run()'e у тебя только испускание сигналов и коннекты, это только частичная многопоточность. А то что на видео - просто демонстрация асинхронной работы load(), не многопоточность это. А ведь работать может понадобиться с каждой загруженной страницей отдельно и методы работы с ними будут разные, 100% не асинхронные грубо говоря.
Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 16:43 Код так это и решал. скучно было ;) Название: Re: Создание/вызов методов в разных потоках. Отправлено: serg_hd от Ноябрь 29, 2009, 16:49 всё там прыгает как надо, но это только загрузка, она бесполезна, нужен отдельный поток, чтобы работать с каждой загруженной страницей (считывать правила работы со страницей например из файла, ставить задержки и т.п. и т.д.). Надо всё же попробовать WebPage и QWebFrame, вдруг покатит, завтра попробую, а то выходной всё-таки.
Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 16:55 niXman, в run()'e у тебя только испускание сигналов и коннекты, это только частичная многопоточность. А то что на видео - просто демонстрация асинхронной работы load(), не многопоточность это. А ведь работать может понадобиться с каждой загруженной страницей отдельно и методы работы с ними будут разные, 100% не асинхронные грубо говоря. вот если бы я впихнул цикл распределения заданий в основной поток, то да, однопоточность. и ГУИ в этом случае практически не прорисовывается(понятно почему), проверено.Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 17:00 Это все хорошо.
Но я писал: Но есть проблема! Может этого и нельзя сделать! ??? WebPage - обязан создаваться в главном потоке, поскольку его родителем будет QWebView Цитировать The child of a QObject must always be created in the thread where the parent was created. Родителем WebFrame является WebPage, все нормально. Предаем его в другой поток, вызываем там WebFrame::load. И наш WebFrame при загрузке создает у себя дочерние QWebFrame !!! Что недопустимо, они должны быть созданы в главном потоке! Никто на это ничего не ответил. Либо я ошибаюсь, либо загружать в WebFrame можно только в главном потоке! Название: Re: Создание/вызов методов в разных потоках. Отправлено: serg_hd от Ноябрь 29, 2009, 17:06 Либо я ошибаюсь, либо загружать в WebFrame можно только в главном потоке! Это конечно плохо. Но лично я не ответил, т.к. не пробовал, попробую - отпишусь, другого варианта всё равно нет, что касается qt jambi конечно.Название: Re: Создание/вызов методов в разных потоках. Отправлено: BRE от Ноябрь 29, 2009, 17:08 Никто на это ничего не ответил. Я это только предположил, проверять не буду - лень/надоело, подожду результаты заинтересованных лиц. :)Либо я ошибаюсь, либо загружать в WebFrame можно только в главном потоке! Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 17:23 Никто на это ничего не ответил. думаю это вполне выполнимо. но нужно ковыряться во внутренностях QWebView. чем и занимаюсь.Либо я ошибаюсь, либо загружать в WebFrame можно только в главном потоке! Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 17:25 Кто-нибудь, подскажите, где есть диаграмма наследования Qt ?
Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 17:28 Либо я ошибаюсь, либо загружать в WebFrame можно только в главном потоке! Это конечно плохо. Но лично я не ответил, т.к. не пробовал, попробую - отпишусь, другого варианта всё равно нет, что касается qt jambi конечно.Просто попробовать здесь может не помочь. В данной ситуации на тестах все может прокататить, а упадет неизвестно когда и тогда уже даже не поймешь что связано с этой проблемой. Надо сперва разобраться. Название: Re: Создание/вызов методов в разных потоках. Отправлено: pastor от Ноябрь 29, 2009, 17:30 Кто-нибудь, подскажите, где есть диаграмма наследования Qt ? см. Class Inheritance Hierarchy Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 17:31 Кто-нибудь, подскажите, где есть диаграмма наследования Qt ? Assistant: Qt Reference Documentation->API Reference->Class Chart Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 17:42 А ведь работать может понадобиться с каждой загруженной страницей отдельно и методы работы с ними будут разные, 100% не асинхронные грубо говоря. Да, в этом случае, моим методом не обойтись. Но я же не это проверял. Просто продемонстрировал возможность одновременной работы вьюшек с распределением заданий из одного потока.А если алгоритм работы с содержимым вьюшек синхронный, значит его в поток. Но вьюшки пихать в тот же поток не за чем! 1. для каждой вьюшки отдельный поток в котором реализован алгоритм. 2. сигналы и слоты этого потока соединяются с этой вьюшкой. 3. так как каждый сценарий выполняется в отдельной потоке, нам нужно декларировать в нем один сигнал, и один слот. 3.1 signalRunScenarie(scenarie); 3.2 slotScenarieFinish(bool); как-то так ;) Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 17:48 Spectre, pastor
спасибо. Кстати в моем примере, на одном ядре 2.3 ггц, для 100% загрузки, нужно запустить 370 вьюшек. памяти съедает 690 метров. Что вполне нормально. Так что если распараллелить программу на несколько ядер, то даже гугл позавидует ;D Название: Re: Создание/вызов методов в разных потоках. Отправлено: Igors от Ноябрь 29, 2009, 18:35 Кстати в моем примере, на одном ядре 2.3 ггц, для 100% загрузки, нужно запустить 370 вьюшек. памяти съедает 690 метров. Что вполне нормально. Так что если распараллелить программу на несколько ядер, то даже гугл позавидует ;D Приятно видеть приличный объем :) Но на одном ядре есть подлянка: часто оно "работает" с нитками, все нормально. А когда запускаем там где физически 2 или более процессора - оно валится. Надо как-то отладить, приходится проситься к кому-то на машину - а это никому не приятно и.т.п. Просто имейте ввиду.Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 19:12 Цитировать Приятно видеть приличный объем Улыбающийся Но на одном ядре есть подлянка: часто оно "работает" с нитками, все нормально. А когда запускаем там где физически 2 или более процессора - оно валится. Надо как-то отладить, приходится проситься к кому-то на машину - а это никому не приятно и.т.п. Просто имейте ввиду. Так это дело техники ;)Кстати у меня 4 ядра, и ничего, работает ;) Название: Re: Создание/вызов методов в разных потоках. Отправлено: niXman от Ноябрь 29, 2009, 19:40 Spectre, pastor, по всем ссылкам что я нашел, есть только чарты версии 4.3 а в ней нет упоминаний про WebKit.
Идеи? Название: Re: Создание/вызов методов в разных потоках. Отправлено: lit-uriy от Ноябрь 29, 2009, 20:14 >>Идеи?
просить тролей обновить PDF'ник Название: Re: Создание/вызов методов в разных потоках. Отправлено: spectre71 от Ноябрь 29, 2009, 20:47 >>Идеи? просить тролей обновить PDF'ник Каие же они ленивые эти тролли. :) Надо посмотреть в Assistant. Есть надежда что там инфа соответствыет версии. Название: Re: Создание/вызов методов в разных потоках. Отправлено: lit-uriy от Ноябрь 29, 2009, 21:35 в новых версиях PDF'ника нету, только текстовая диаграмма
http://doc.trolltech.com/4.5/hierarchy.html Название: Re: Создание/вызов методов в разных потоках. Отправлено: AlekseyK от Октябрь 03, 2010, 22:09 Граждане, ну и чем закончился разбор полётов?! QWebFrame->load() в отдельном потоке работает??? Я пробовал создать QWebPage в отдельном потоке, а потом передавать его в QWebVeiw через setPage() - валится. Может лучше как-то копую WebPage передавать в QWebView??? Как создать копию?
Название: Re: Создание/вызов методов в разных потоках. Отправлено: AlekseyK от Октябрь 04, 2010, 00:33 QWebFrame->load() в отдельном потоке работает??? Вроде работает. |