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

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

Страниц: 1 [2] 3 4   Вниз
  Печать  
Автор Тема: QThread, как с ним работать, где почитать подробно?  (Прочитано 32847 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #15 : Март 30, 2010, 08:50 »

Цитировать
вставьте тестовую печать thread() для объектов сигнал/слот

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

если главная нить создала ранее в куче объект (не наследует QObject, вообще ничего не наследует, сам по себе), и есть глобальный указатель на его тело, можно из QThread обращаться напрямую к методам этого объекта, при условии, что ни он сам, ни его вызовы не вызывают другие функции из объектов главной нити, и не работают с интерфейсом, но вызывают некие нейтральные функции, написанные на С?
« Последнее редактирование: Март 30, 2010, 09:00 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #16 : Март 30, 2010, 09:10 »

нет, нельзя. ты должен гарантировать, что никто не вызовет методов объекта из мейн треда пока ты работаешь из 2го
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #17 : Март 30, 2010, 09:26 »

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

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

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #18 : Март 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-го треда?
Обращаться, вызывать методы и.т.п. можно, если по чтению - то из любого числа ниток. А вот по записи - нужно обеспечить блокировки что иногда бывает очень непросто. "Гарантированно никто не обратится" - утверждение весьма смелое, часто это бывает не так.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #19 : Март 30, 2010, 13:16 »

ну если локеров не наставить, так и будет:)
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #20 : Март 30, 2010, 15:12 »

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

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

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

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

2^7-1 == 127, задумайтесь...
BRE
Гость
« Ответ #21 : Март 30, 2010, 15:23 »

2 Гурман
Покажи как ты нить запускаешь и что в run нити находиться.

Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #22 : Март 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)));
}

ничего не изменилось  Непонимающий
« Последнее редактирование: Март 30, 2010, 15:51 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #23 : Март 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
« Последнее редактирование: Март 30, 2010, 16:04 от Авварон » Записан
BRE
Гость
« Ответ #24 : Март 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 )).
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #25 : Март 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 и никакой другой.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #26 : Март 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 приходится делать?

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

и это тоже попробую
Записан

2^7-1 == 127, задумайтесь...
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #27 : Март 30, 2010, 20:09 »

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

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

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

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #28 : Март 30, 2010, 20:11 »

Цитировать
как всетаки поток запускается? thread->run()?

processthread->run();

я сначала хотел там свой признак сделать, что процесс уже запущен
« Последнее редактирование: Март 30, 2010, 20:13 от Гурман » Записан

2^7-1 == 127, задумайтесь...
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #29 : Март 30, 2010, 20:15 »

Воспользуйся всетаки советом BRE и измени код запуска
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Страниц: 1 [2] 3 4   Вверх
  Печать  
 
Перейти в:  


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