Russian Qt Forum

Qt => Общие вопросы => Тема начата: Гурман от Март 29, 2010, 11:32



Название: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 29, 2010, 11:32
некий транслятор создает некий код для некоего интерпретатора (не QScript) и потом надо запустить интерпретатор, чтобы этот код выполнялся в независимой нити, а управление могло вернуться в объект, связанный с пользовательским интерфейсом, то есть, чтобы пользователь мог видеть результаты выполнения кода, что-то еще делать, не связанное с изменением этого кода

как это правильно сделать? где можно подробнее прочитать о работе QThread, с несколькими примерами, использование start()/exit() и т.д.

попытка выполнить в run() просто сначала start(), потом запустить интерпретатор, приводит к падению интерпретатора, некоторые данные в коде оказываются разрушены, хотя во время его выполнения ничего больше не делается, но падает не сразу, интерпретатор выполняет несколько первых инструкций, в том числе, достаточно сложных, работающих со стеком, и с объектами в куче, но потом похоже портится куча, поскольку интерпретатор получает, вместо указателя на объект в куче, указатель 0xfeeefeee

при запуске в приложении в одной нити этот же интерпретатор работает на ура, выполняется все замечательно, проблем нет вообще никаких

в общем, где хорошо описан QThread и есть примеры решения похожих задач?


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: garryHotDog от Март 29, 2010, 12:25
Привет! Во первых документация QT! Во вторых google.com (он знает все) ;D....а вообще во всех книгах по Qt все расписано оч. хорошо...вот напримре книга - http://lib.rus.ec/b/138880 (http://lib.rus.ec/b/138880)


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 29, 2010, 12:44
по документации не видно почти ничего, нет никаких тонкостей...

книга эта есть в печатном виде, и там тоже нет ответа на мой вопрос - почему может портиться куча (пока единственный разумный ответ - куча в библиотеках MinGW не имеет встроенной защиты на случай многопоточности, в отличие от MFC, хотя это выглядит более чем странно), как надо бы строить приложение и взаимодействие объектов, наследующих QThread, как правильнее использовать сигналы-слоты в этом случае (например, мне надо из одного треда в другой передавать строки, как правильно реализовать очередь строк, если тредов интерпретатора будет запущено несколько?)

а про мутексы и семафоры я читал, пародон, в начале 90-х, тут у Шлее нет ничего для меня нового


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Авварон от Март 29, 2010, 12:58
ну раз читал, то и используй их


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Igors от Март 29, 2010, 12:58
Может быть лучше сделать сначала например простое чтение файла: унаследоваться от QThread, определить run() и наладить взаимодействие между читающим run и индикатором загрузки файла, который в главной нитке. Потом будет гораздо яснее с интерпретатором и.т.п. Сейчас во всех книгах Вы найдете примерно одинаковые фразы, которые конечно правильны, но не дают почувствовать на практике.


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 29, 2010, 13:09
мне не надо из файла читать, у меня есть окно, в которое производится вывод сообщений, как в консоль, интерпретатор выводит туда сообщения, несколько появляются, потом падение по ошибке обращения по несуществующему адресу или в интерпретаторе, или где-то в коде Qt, который выводит текст в окно, во всех случаях проблемы с динамически захваченными объектами, испорчены указатели

Цитировать
ну раз читал, то и используй их

где?? самому переписать распределение памяти с защитой на семафорах??? :o

в интерпретаторе есть куски старого кода на С, который использует malloc/calloc - с MFC все работало на ура, запускали интерпретатор в отдельном треде, программы выполнялись, при этом интерфейс задачи был живой, работал, интерпретатор хватал себе куски памяти, интерфейс программы и она сама тоже хватали себе куски памяти, никаких конфликтов не было

а сейчас ощущение такое, будто конфликт возникает при распределении памяти, рушится куча, иначе пока трудно объяснить, почему при выводе сообщений все рассыпается

есть правда еще одна мысль... надо ее проверить...

Цитировать
Сейчас во всех книгах Вы найдете примерно одинаковые фразы

ну я об этом и спрашиваю, может где-то уже есть более подробно описанная работа с QThread и сигнал-слотами, может на веб-страницах, блогах, уже хорошо известное... гуглом буду долго искать, а надо дело делать

/*забыл написать, что вопрос тем, кто знает ответ, а не умеет предлагать пользоваться поисковиками - как правило, их советуют те, кто сам только недавно научился ими пользоваться*/


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Igors от Март 29, 2010, 13:33
/*забыл написать, что вопрос тем, кто знает ответ,
Ответ на что?  "Почему валится моя задача?"  :)

1) Где почитать: Assistant.
а) описание класса QThread
б) описание типов connect
в) метод thread для QObject

2) Распределения памяти сводятся к malloc который thread-safe, так что переписывание распределения памяти от Вас не требуется

3)
мне не надо из файла читать, у меня есть окно, в которое производится вывод сообщений, как в консоль, интерпретатор выводит туда сообщения, несколько появляются, потом ...
Если уж Вы такой быстрый и тратить время на учебный пример не желаете, то стоит проверить, не лезете ли Вы в окно из нитки расчета - здесь Вы точно crash получите т.к. все вызовы UI должны выполняться только в главной нитке


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: developer от Март 29, 2010, 13:39
http://www.ics.com/learning/icsnetwork/

Посмотри сюда, здесь видео уроки от ICS, по нитях там очень хорошо расказано.


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: pastor от Март 29, 2010, 13:42
Гурман, выложи код сюда, посмотрим почему валится.

Про работу с потоками ты также можешь почитать в разделе ассистанта Thread Support in Qt


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 29, 2010, 14:04
Цитировать
стоит проверить, не лезете ли Вы в окно из нитки расчета

ну так оно и есть... несколько удручен, что в такой мощной штуке, как Qt, интерфейсные объекты могут работать только в главной нити :( раньше этого не замечал, поскольку казалось, что такого быть просто не может

причем это буквально удар под дых...  >:(

хотя данная проблема разрешилась связью объекта-интерпретатора и окна сообщений через сигнал-слот, удручает, что нельзя простым способом в интерпретаторе создавать интерфейсные объекты :(

очень удручает...


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Igors от Март 29, 2010, 14:38
..данная проблема разрешилась связью объекта-интерпретатора и окна сообщений через сигнал-слот,
А Вы уверены что разрешилась? Или просто "сейчас не падает"? Проверьте на всякий случай тип коннекта


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 29, 2010, 15:18
не, не разрешилась

причем если явно указывать Qt::QueuedConnection, то не работает вообще, выводится одна строка правильно, за ней некорректная, и все заканчивается

а по умолчанию похоже связывает через Qt::DirectConnection, потом не падает, но не успевает выводить целиком все строки (QTextEdit)


и хоть бы где было написано, что run() еще раз вызывается в start()...  >:(


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: lit-uriy от Март 29, 2010, 15:27
>>а по умолчанию похоже связывает через Qt::DirectConnection
нет не прямое, в асиситенте написан тип умалчиваемого соединения. Тут гадать не зачем


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 29, 2010, 15:32
там написано, что по умолчанию Qt::QueuedConnection, но если его явно указать, то не работает, если попытаться QBlockingQueuedConnection, эффект точно такой же

а если через очередь, то почему не все строки успевают вставляться в QTextEdit?


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Igors от Март 29, 2010, 16:01
там написано, что по умолчанию Qt::QueuedConnection, но если его явно указать, то не работает, если попытаться QBlockingQueuedConnection, эффект точно такой же
Перед вызовом connect вставьте тестовую печать thread() для объектов сигнал/слот чтобы посмотреть где они были созданы. Ну и вообще консоль смотрите, там Qt часто выводит полезную информацию


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 30, 2010, 08:50
Цитировать
вставьте тестовую печать thread() для объектов сигнал/слот

немного не понял, что здесь имеется в виду, что за "тестовая печать thread()"

если главная нить создала ранее в куче объект (не наследует QObject, вообще ничего не наследует, сам по себе), и есть глобальный указатель на его тело, можно из QThread обращаться напрямую к методам этого объекта, при условии, что ни он сам, ни его вызовы не вызывают другие функции из объектов главной нити, и не работают с интерфейсом, но вызывают некие нейтральные функции, написанные на С?


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Авварон от Март 30, 2010, 09:10
нет, нельзя. ты должен гарантировать, что никто не вызовет методов объекта из мейн треда пока ты работаешь из 2го


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 30, 2010, 09:26
даже при том, что объект висит в воздухе, и из главного треда к нему нет обращений, нельзя к нему обратиться из 2-го? ужос...  ???

а если это не методы, но обычные С call style или C++ call style функции, и они работают с общими глобальными структурами данных, и ко всему этому гарантированно никто не обратится во время выполнения 2-го треда?


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Igors от Март 30, 2010, 12:53
немного не понял, что здесь имеется в виду, что за "тестовая печать thread()"
Код:
connect(src, SIGNAL(..), dst, SLOT(..), ..);
qDebug() << "src " << src->thread();
qDebug() << "dst " << dst->thread();
Тогда будет ясно какой тип connect подойдет

даже при том, что объект висит в воздухе, и из главного треда к нему нет обращений, нельзя к нему обратиться из 2-го? ужос...  ???

а если это не методы, но обычные С call style или C++ call style функции, и они работают с общими глобальными структурами данных, и ко всему этому гарантированно никто не обратится во время выполнения 2-го треда?
Обращаться, вызывать методы и.т.п. можно, если по чтению - то из любого числа ниток. А вот по записи - нужно обеспечить блокировки что иногда бывает очень непросто. "Гарантированно никто не обратится" - утверждение весьма смелое, часто это бывает не так.


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Авварон от Март 30, 2010, 13:16
ну если локеров не наставить, так и будет:)


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 30, 2010, 15:12
там так - основная нить по командам пользователя готовит данные в объекте, после того, как они готовы, пользователь запускает вторую нить, блокируется возможность изменения данных первой нитью, вторая нить их читает и меняет, при этом первая нить может читать, но менять никак не может, хотя сейчас она их даже не читает, у пользователя пока только есть возможность подать через слот команду второй нити на завершение

что еще пока не понятно - после старта второй нити, интерфейсные функции в первой перестают ловить действия пользователя, вообще интерфейс приложения блокируется, окно нельзя перемещать, перекрытые области не перерисовываются, только идет вывод в область, где отображается объект с текстом, получаемым от второй нити

хотя это может быть, из-за того, что при тестировании там вывод идет очень активно, и даже перерисовка не успевает, но приложение берет только 25% CPU, должно успевать - как только 2я нить умирает, окно перерисовывается, восстанавливается, и получает все сигналы  ???

а соединение проверю... хотя больше похоже, что оно все-таки прямое, не через очередь


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: BRE от Март 30, 2010, 15:23
2 Гурман
Покажи как ты нить запускаешь и что в run нити находиться.



Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 30, 2010, 15:40
вот так...

Код:
void ProcessThread::run()
{
start();
DataProcessor->Process();
}

DataProcessor - объект, построенный основной нитью, лежит по глобальному указателю (пока так удобнее)

еще у класса ProcessThread есть метод
Код:
void ProcessThread::ConsoleMessage( QString message )
{
emit sigConsoleMessage( message );
}

который вызывается из extern "C" функции void thread_stream( char* msg ), которая вызывается глубоко изнутри DataProcessor->Process() при необходимости вывода текста, сигнал связан со слотом в основной нити (связывается в конструкторе)

Код:
ProcessThread::ProcessThread(MainWindow *frontend) : QThread(frontend)
{
connect( this, SIGNAL(sigConsoleMessage(QString)), frontend, SLOT(slMessage(QString))/*, Qt::QueuedConnection*/);
}

ой... я кажется вижу косяк... С-функция вызывает метод главного окна из первого треда... блин... правда она это делает, только чтобы указатель на объект второго треда получить, вот так:

Код:
extern "C" void thread_stream( char* msg )
{
frontend->processThread()->ConsoleMessage(QString(QObject::tr(msg)));
}

где MainWindow::processThread(){return processthread;} там при создании заносится указатель на объект во второй нити

так тоже нельзя?...  :-[

приделал статический указатель ProcessThread* processThread , занес в него this в конструкторе ProcessThread, стал вызывать печать через него

Код:
extern "C" void thread_stream( char* msg )
{
processThread->ConsoleMessage(QString(QObject::tr(msg)));
}

ничего не изменилось  ???


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Авварон от Март 30, 2010, 16:01
void ProcessThread::run()
{
   //start(); //убрать
   DataProcessor->Process();
}
в мейн нитке ProcessThread * thread = new ProcessThread();
thread->start();

ЯХЗ как надо читать документацию:
Цитировать
void QThread::run ()   [virtual protected]
The starting point for the thread. After calling start(), the newly created thread calls this function.
и вот даже пример есть http://doc.trolltech.com/4.6/threads-waitconditions.html


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: BRE от Март 30, 2010, 16:10
Ты примеры смотрел?

Новый поток запускается методом start():
Код
C++ (Qt)
ProcessThread *thread = new ProcessThread;
thread->start();
 

Весь код, который должен выполниться в отдельной нити располагается в run():
Код
C++ (Qt)
void ProcessThread::run()
{
       DataProcessor->Process();
}
 

Объект thread (класса ProcessThread) принадлежит главной (или создающей) нити, поэтому в connect нужно указывать явно тип соединения Qt::QueuedConnection или перед коннектом нужно указать, что этот объект должен принадлежать дочернему потоку (смотри void QObject::moveToThread ( QThread * targetThread )).


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Igors от Март 30, 2010, 16:45
Код:
ProcessThread::ProcessThread(MainWindow *frontend) : QThread(frontend)
{
connect( this, SIGNAL(sigConsoleMessage(QString)), frontend, SLOT(slMessage(QString))/*, Qt::QueuedConnection*/);
}
Оба (this и frontend) созданы в одной (главной) нитке, а сигнал на обновление UI посылается из дочерней нитки в главную. Поэтому обязательно использовать Qt::QueuedConnection и никакой другой.


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 30, 2010, 19:50
Ты примеры смотрел?

а как же! я же в начале ветки про примеры спрашивал, искал...
запускать start() в run() не сам придумал, в каком-то примере увидел

по идее, там без разницы где start() делать, при первом его вызове стартует нить и устанавливается флаг внутри QThread (я по start() отладчиком прошел), после чего в конце start() выполняется run(), при повторном входе в start сразу проверка на флаг и выход если он взведен, то есть, DataProcessor->Process() выполняется уже в нити

Цитировать
Оба (this и frontend) созданы в одной (главной) нитке, а сигнал на обновление UI посылается из дочерней нитки в главную. Поэтому обязательно использовать Qt::QueuedConnection и никакой другой.

ну вот в случае Qt::QueuedConnection или Qt::BlockingQueuedConnection все наглухо виснет

попробую start() из фронтенда вызвать, но не уверен, что это что-либо даст

там точно нигде не надо какую-нибудь multithreading model включить специально, как это при работе с MFC приходится делать?

Цитировать
перед коннектом нужно указать, что этот объект должен принадлежать дочернему потоку

и это тоже попробую


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: pastor от Март 30, 2010, 20:09
а как же! я же в начале ветки про примеры спрашивал, искал...
запускать start() в run() не сам придумал, в каком-то примере увидел

Это не првильно вызывать start() в run(). И как всетаки поток запускается? thread->run()?

А ведь в ассистанте написано и примеры есть. (ссылку кидал выше; да даже в самом описании класса QThread есть ссылки на примеры)


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 30, 2010, 20:11
Цитировать
как всетаки поток запускается? thread->run()?

processthread->run();

я сначала хотел там свой признак сделать, что процесс уже запущен


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: pastor от Март 30, 2010, 20:15
Воспользуйся всетаки советом BRE и измени код запуска


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: BRE от Март 30, 2010, 20:19
Цитировать
как всетаки поток запускается? thread->run()?
processThread()->run();
Смотри что происходит при этом:
Вызывается метод run в главном потоке;
Вызывается start, при этом создается новый поток в котором начинает выполняться метод run;
После отработки start продолжает выполняться run в главном потоке (DataProcessor->Process());
Выполняется DataProcessor->Process() в дочернем потоке.

Поэтому у тебя GUI и останавливается.



Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 31, 2010, 06:55
Цитировать
После отработки start продолжает выполняться run в главном потоке (DataProcessor->Process())

по коду в главном потоке вызова DataProcessor->Process() не должно происходить, поскольку start у меня рекурсивно вызывал run, сам повторно не выполнялся, так как уже выполнился, и только после этого начинал выполняться Process()

но возможно из-за неправильной последовательности вызовов что-то происходит не так, согласен, доеду до работы, проверю


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: BRE от Март 31, 2010, 07:46
по коду в главном потоке вызова DataProcessor->Process() не должно происходить, поскольку start у меня рекурсивно вызывал run, сам повторно не выполнялся, так как уже выполнился, и только после этого начинал выполняться Process()
start создает контекст дочерней нити и в нем заново запускает run. В контексте дочернего потока start сразу выходит и запускает Process, но в главном потоке управление получает следующая строка после start и соответственно запускается свой Process.


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 31, 2010, 08:47
да, так и есть Process() запускался дважды

заработало, но только с Qt::BlockingQueuedConnection, если просто Qt::QueuedConnection то интерфейс все равно не работает, хотя строки выводятся

теперь такой вопрос: QThread::isRunning () is thread-safe? можно его вызывать из главной нити, чтобы определить выполняется вторая, или уже завершилась?


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: BRE от Март 31, 2010, 08:49
заработало, но только с Qt::BlockingQueuedConnection, если просто Qt::QueuedConnection то интерфейс все равно не работает, хотя строки выводятся
Покажи побольше кода.
Тяжело телепатировать.  ;)


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 31, 2010, 08:54
Цитировать
Покажи побольше кода.

какого? всего? десятки тысяч строк... ;D

- убрал вызов start() внутри run()
- заменил вызов run() на start() в главной нити
- убрал комментарии при соединении объектов, получилось

Код:
	connect( this, SIGNAL(sigConsoleMessage(QString)), pMainWindow, SLOT(slMessage(QString)), Qt::QueuedConnection);

работает почти правильно, порождается один процесс обработки (вчера точно было 2, я видел вывод обоих, и не понимал, откуда берется второй), но интерфейс блокирован, заменяю на Qt::BlockingQueuedConnection - все работает



Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: BRE от Март 31, 2010, 09:05
Нее, весь не надо...

Покажи что за объект DataProcessor, как описан его класс, как он создается, хотя бы примерно что находиться в методе Process, где вызывается thread_stream?


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 31, 2010, 09:16
это большой объект, он связан с данными, построенными в главной нити, но конкретно метод Process вызывает библиотеку, написанную на С, и там производится обработка данных

Код:
bool SomeClass::Process()
{
    // здесь сначала некоторые проверки значений полей класса SomeClass, никаких внешних обращений
    return execute( FALSE );  // это функция на С
}

создается объект в главной нити, этот класс никого сам не наследует, но его наследует один из классов, работающих в главной нити, причем потомок напрямую связан с Qt, и занимается отрисовкой обрабатываемых данных

далее в объекте класса SomeClass, в его методах, в библиотеке на С, никакие классы Qt не вызываются и не используются, гарантированно, этот класс и дальнейшая обработка ранее отлажены без использования Qt, единственная связь с Qt только в выдаче сообщений во время работы второй нити, она через функцию-хук thread_stream( char* msg )

на самом деле, перед выполнением , заменяется точка входа в функцию выдачи сообщений, которую вызывает С-библиотека, потом она восстанавливается

Код:
void ProcessThread::run()
{
messasge_function = thread_stream; // ее код был ранее
        DataProcessor->Process();
messasge_function = print_stream;
}

где message_function глобальный extern "C" указатель на функцию, print_stream - указатель на функцию, которая производит выдачу сообщений, когда вторая нить не активна

сейчас гарантировано, что во время выполнения второй нити, сообщения выдаваться не могут

возможно есть смысл вызывать extern "C" int execute() прямо из run(), правда тогда придется продублировать поля из SomeClass, поскольку организовывать его взаимодействие с ProcessThread никак нельзя, SomeClass должен остаться Qt-независимым



Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: BRE от Март 31, 2010, 09:23
К объекту DataProcessor кто-то еще обращается из главного потока?
Какие-то объекты синхронизации используются?


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 31, 2010, 09:29
Цитировать
К объекту DataProcessor кто-то еще обращается из главного потока?

нет

Цитировать
Какие-то объекты синхронизации используются?

нет

во время выполнения второй нити, этот объект вообще не затрагивается никем, модифицировать его запрещено, а читать незачем, С-библиотеке он не нужен, она работает со структурами данных (таблицами), которые ранее строятся главной нитью по данным из этого объекта


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Авварон от Март 31, 2010, 10:45
а разве чтобы нормально работали сигналы\слоты в треде, вызов exec() не нужен?
моё имхо - надо run вообще не переобпределять, сделать слот calc() и его из мейна дергать через InvokeMathod с QueuedConnection когда надо запстить расчеты. А start() нити звать в конструкторе оной к примеру


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: BRE от Март 31, 2010, 11:05
а разве чтобы нормально работали сигналы\слоты в треде, вызов exec() не нужен?
Для отсылки сигнала - нет, а вот для получения и вызова слота - нужен.



Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Авварон от Март 31, 2010, 11:14
ааа, ясно, спасибо.


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 31, 2010, 11:45
работает пока с Blocking, потом придется вернуться, и разобраться почему просто очередь не работает, но как-то все это грустно...  :(

в BeOS 15 лет назад был аналогичный сигналам-слотам механизм, можно было плодить какие хочешь треды, передавать любые объекты через соединения, и уже про мутексы и семафоры с ними можно было практически не вспоминать, даже можно было напрямую методы из соседних нитей вызывать, лишь бы они одновременно не модифицировали внешние по отношению к ним данные, а обращаться на чтение сколько угодно


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Igors от Март 31, 2010, 12:22
Код:
	connect( this, SIGNAL(sigConsoleMessage(QString)), pMainWindow, SLOT(slMessage(QString)), Qt::QueuedConnection);
работает почти правильно, порождается один процесс обработки (вчера точно было 2, я видел вывод обоих, и не понимал, откуда берется второй), но интерфейс блокирован, заменяю на Qt::BlockingQueuedConnection - все работает
Разберитесь в каких нитках были созданы сигнал/слот (this и pMainWindow). В сложной программе проще это напечатать в консоль. Если BlockingQueuedConnection вообще работает - они были созданы в разных.

работает пока с Blocking, потом придется вернуться, и разобраться почему просто очередь не работает, но как-то все это грустно...  :(
Что грустно-то? Что не заработало с пол-пинка?  :)

в BeOS 15 лет назад был аналогичный сигналам-слотам механизм, можно было плодить какие хочешь треды, передавать любые объекты через соединения, и уже про мутексы и семафоры с ними можно было практически не вспоминать, даже можно было напрямую методы из соседних нитей вызывать, лишь бы они одновременно не модифицировали внешние по отношению к ним данные, а обращаться на чтение сколько угодно
Никто не мешает читать и вызывать методы объектов созданных в др. нитках, они должны быть thread-safe - в Qt и везде. Про мутексы и семафоры вспомнить придется если пишете/читаете в разных нитках. Горести по поводу отсутствия какого-то "особенного" сервиса у Qt лишены оснований поскольку все эти вещи/понятия общие для multi-threading и для любого OC и любая библиотека может только сделать это более удобным.


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 31, 2010, 15:00
Цитировать
Что грустно-то?

в первую очередь, что нельзя в тредах использовать интерфейсные объекты Qt, то есть, если нужно два окна с кнопками, чтобы в окнах отображались результаты работы асинхронных процессов, кнопки управляли процессами независимо, но при этом процессы легко между собой общались - также элементарно просто, как это было заложено в BeOS, на Qt не сделать  :(

я тогда похожую программу написал минут за 30, менее 100 строк, и она работала без проблем и сразу

ладно, проехали... может еще будет все...

Цитировать
Что не заработало с пол-пинка?

с полпинка без Blocking почему-то не работает цикл сообщений главной нити - не ловятся сигналы, нет перерисовки окна при перекрытии, хотя может здесь дело совсем в другом

но с Blocking все работает, причем ровно как надо - бэкэнд в фоне работает, фронтэнд тоже, курсор по нему ходит, просмотр есть, редактирование запрещается при старте бэкэнда, по завершении бэкэнд выдает сигнал finished(), соответствующий слот фронтэнда разрешает редактирование...


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Авварон от Март 31, 2010, 15:24
ни в 1й ОС нельзя работать с гуями не из главного потока, ага?


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: pastor от Март 31, 2010, 15:25
ни в 1й ОС нельзя работать с гуями не из главного потока, ага?

Неправда, даже в винде можно. Гугл в помощь


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Авварон от Март 31, 2010, 15:42
линк плз. Я лично не очень представляю механизм ресайза в таком случае.


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: pastor от Март 31, 2010, 16:09
Джеффри Рихтер. Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows (главы 6, 26, 27)


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 31, 2010, 17:49
давайте без оффтопика... но в BeOS легко создавались 2 окна, в которые независимые треды выводили текстовые сообщения, и легко осуществлялся обмен текстовыми сообщениями между тредами через аналоги сигнал-слотов, так, что сообщения отправленные из одного треда, появлялись в окне, связанном с другим

в винде тоже можно, хотя не так изящно, как в BeOS

невозможность делать это в Qt СИЛЬНО ограничивает его применимость :(

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


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: BRE от Март 31, 2010, 18:06
давайте без оффтопика... но в BeOS легко создавались 2 окна, в которые независимые треды выводили текстовые сообщения, и легко осуществлялся обмен текстовыми сообщениями между тредами через аналоги сигнал-слотов, так, что сообщения отправленные из одного треда, появлялись в окне, связанном с другим

в винде тоже можно, хотя не так изящно, как в BeOS

невозможность делать это в Qt СИЛЬНО ограничивает его применимость :(
В Qt это возможно и делается элементарно.

и вообще, при необходимости многозадачности сползать на уровень мутексов и семафоров... это все равно, как при необходимости писать в файл, приходилось бы самостоятельно следить за буфером и прерываниями, уж сейчас мог бы существовать более мощный механизм, тем более, в таком развитом инструменте, как Qt
В assistant посмотри на QtConcurrent, это Qt.
Посмотри на OpenMP.


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Март 31, 2010, 18:26
видел, но той изящности и простоты, что была в BeOS, QtConcurent был бы не конкурент

а OpenMP это вообще несколько из другой оперы, хотя еще Тролли могли бы расширить MOC до поддержки мультизадачности на уровне специальных расширений языка


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Апрель 05, 2010, 10:06
up...

ну положим, вторая нить приторможена, причем находится в wait( мутекс )

надо в нее передать сигнал, согласно документации, если нить крутится, то для приема сигналов надо запускать ее очередь сообщений exec()

а если нить стоит? насколько обязателен exec()? вижу, что у стоящей нити можно вполне безопасно менять общие глобальные данные (но не хочется этим баловаться, через сигналы правильнее) - а как насчет передачи сигналов именно ОСТАНОВЛЕННОЙ нити?

в общем, оно работает нормально без exec() в данном случае, вопрос скорее в том, насколько запуск обработчика сообщений идеологически обязателен


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Igors от Апрель 05, 2010, 13:18
ну положим, вторая нить приторможена, причем находится в wait( мутекс )
Код:
MyThread thread;
..
thread.wait();
Нитка в которой создался MyThread и которая вызвала wait - будет стоять и никакими сигналами ее не сдвинуть. Однако созданная thread будет выполнять свой run, когда он кончится, вызывающий разблокируется.

Код:
MyThread::run( void )
{
  ..
  mutex.lock();
  ...
  mutex.unlock();
}
Если мутекс заперт, нитка ждет его освобождения, которое должен выполнить только тот кто этот мутекс захватил. Сигналы могут накапливаться в очереди но никак не помогут сняться с мутекса.

В обоих случаях есть exec или нет - не решает вопрос блокировки.

вижу, что у стоящей нити можно вполне безопасно менять общие глобальные данные (но не хочется этим баловаться, через сигналы правильнее)
Ну в принципе для этого мутекс и предназначен (хотя не все так просто как кажется). Посылать остановленной нитке сигнал бессмысленно


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Апрель 05, 2010, 15:11
Посылать остановленной нитке сигнал бессмысленно

как оказывается - вовсе нет

ветка остановлена, как в мануале написано:
Код:
	QMutex pausemutex;
pausemutex.lock();
paused_condition->wait( &pausemutex );
pausemutex.unlock();

запускается из метода, находящегося в этом же классе

Код:
	paused_condition->wakeAll();

так вот, сигнал, передаваемый по соединению от главной нити к остановленной, самой остановленной веткой на ура принимается и обрабатывается - причем соединение делается "по-умолчанию", то есть должно быть через очередь

в конце-концов, без запуска цикла сообщений, это же получается всего-навсего вызов функции в остановленной нитке...


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Igors от Апрель 05, 2010, 17:52
так вот, сигнал, передаваемый по соединению от главной нити к остановленной, самой остановленной веткой на ура принимается и обрабатывается - причем соединение делается "по-умолчанию", то есть должно быть через очередь
Без компилябельного примера точно не сказать - но вряд ли. Наверное сигнал был создан с DirectConnection и он действительно выполняется в том смысле что можно напр. звать  методы объекта и.т.п. - но это выполняется в нитке испускающего сигнал.


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Гурман от Апрель 05, 2010, 19:56
Цитировать
Наверное сигнал был создан с DirectConnection и он действительно выполняется

сигнал был создан с соединением по-умолчанию, а вроде как для потомков QThread по-умолчанию соединение создается через очередь

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

Цитировать
но это выполняется в нитке испускающего сигнал

а какая разница, если нить приемника стоит? оно может и через очередь также точно выполняться... мне не важно, в каком треде выполнилась обработка - ведь второй тред все равно стоит внутри paused_condition->wait( &pausemutex ) и ждет, пока его разбудят, а разбудят его совершенно точно после того, как будет обработан принятый сигнал


Название: Re: QThread, как с ним работать, где почитать подробно?
Отправлено: Igors от Апрель 05, 2010, 22:12
сигнал был создан с соединением по-умолчанию, а вроде как для потомков QThread по-умолчанию соединение создается через очередь
Зачем "вроде как" если это можно знать точно за пару минут?  :) Выбор AutoConnection не зависит от QThread или др. конкретного класса. Если оба объекта были созданы в 1 нитке (а значит используют один EventLoop) - то DirectConnection, иначе Queued.

а какая разница, если нить приемника стоит? оно может и через очередь также точно выполняться... мне не важно, в каком треде выполнилась обработка - ведь второй тред все равно стоит внутри paused_condition->wait( &pausemutex ) и ждет, пока его разбудят, а разбудят его совершенно точно после того, как будет обработан принятый сигнал
Ну и хорошо, так делать можно, а нужно ли - от задачи зависит.