Russian Qt Forum
Март 28, 2024, 14:27
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Многопоточное программирование, процессы
>
Очереди, самодельные сигналы
Страниц:
1
...
5
6
[
7
]
8
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Очереди, самодельные сигналы (Прочитано 71028 раз)
BRE
Гость
Re: Очереди, самодельные сигналы
«
Ответ #90 :
Август 19, 2010, 18:36 »
Цитата: labview от Август 19, 2010, 18:27
Встроил дибаг-сообщения в отправителя сигнала, получателя сигнала и потока. Получатель сигнала (слот) определён в классе QThread, отправитель в главном потоке, DirectConnection не использую. Почемуто номера потоков отправителя и получателя совпадают.
Без исходников трудно сказать, но как мне кажется ты не учел, что сам объект QThread создается в контексте создающего потока.
Посмотри на:
void QObject::moveToThread ( QThread * targetThread )
А лучше покажи свой пример, так будет проще все исправить.
Записан
labview
Гость
Re: Очереди, самодельные сигналы
«
Ответ #91 :
Август 19, 2010, 18:43 »
Да, QThread создаётся в main.cpp(а где ему ещё создаваться?), и отправитель сигнала тоже относится к главному потоку.
Мув посмотрю, спасибо.
Код находится здесь:
http://www.prog.org.ru/index.php?topic=14556.msg95023#msg95023
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Очереди, самодельные сигналы
«
Ответ #92 :
Август 19, 2010, 20:09 »
Цитата: labview от Август 19, 2010, 17:08
На вопрос обработки сигнала в run() я ответа не получил. Получается если в слоте/слотах я выполняю действия с обьектом, то зачем мне нужен run()?
Как уже подробно обсуждалось в этой теме, Вы можете просто построить все на слот/сигнал (обмен через eventLoop), или перекрыть run и сделать свою очередь. Или даже использовать и то и другое (вычурно но возможно).
Цитата: labview от Август 19, 2010, 17:08
Я хотел чтобы обьект (как и реальный) жил своей жизнью (параллельно к другим), но если от обьекта ничего не требуется, то и спал бы себе.
...
Такой вопрос: если файл с траекторией очень большой (например 1 гиг), то зачем мне держать его в памяти?
В памяти или читать с диска - не суть. Чтение траектории не выглядит тем что "может жить своей жизнью". Вот если бы Вы такие запросы получали от 2 и более ниток - имело бы смысл делать это параллельно с др. операциями. А если все равно "блок алгоритм" ждет - чего без толку плодить нитки?
Цитата: labview от Август 19, 2010, 18:43
Да, QThread создаётся в main.cpp(а где ему ещё создаваться?), и отправитель сигнала тоже относится к главному потоку.
А как connect создавали? Указали тип QueuedConnection?
Записан
labview
Гость
Re: Очереди, самодельные сигналы
«
Ответ #93 :
Август 19, 2010, 20:14 »
Цитата: Igors от Август 19, 2010, 20:09
В памяти или читать с диска - не суть. Чтение траектории не выглядит тем что "может жить своей жизнью". Вот если бы Вы такие запросы получали от 2 и более ниток - имело бы смысл делать это параллельно с др. операциями. А если все равно "блок алгоритм" ждет - чего без толку плодить нитки?
С этим согласен, я был не согласен с тем, чтобы считать всю траекторию в память.
Цитата: Igors от Август 19, 2010, 20:09
А как connect создавали? Указали тип QueuedConnection?
Пробовал Auto, Queued и Direct, всё один результат.
Записан
labview
Гость
Re: Очереди, самодельные сигналы
«
Ответ #94 :
Август 19, 2010, 20:54 »
Хотелось бы добить идею со своим листом, а не с сигналами и слотами. Сделал вот так:
Код:
#include "Tasking.h"
Tasking::Tasking()
{
}
Tasking::~Tasking()
{
}
task Tasking::getTask()
{
while(taskList.empty())
cond.wait(&mutex, ULONG_MAX);
mutex.lock();
task currentTask = taskList.takeFirst();
mutex.unlock();
return currentTask;
}
void Tasking::addTask(task newTask)
{
mutex.lock();
taskList.append(newTask);
mutex.unlock();
cond.wakeOne();
}
Но при запуске проги получаю вот такую ошибку:
Код:
Starte D:\C++\Tasking-build-desktop\debug\Tasking.exe...
ASSERT failure in QMutex::unlock(): "A mutex must be unlocked in the same thread that locked it.", file thread\qmutex.cpp, line 371
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
D:\C++\Tasking-build-desktop\debug\Tasking.exe beendet, Rückgabewert 3
Что не так с мьютексом? С помощью него я хотел защитить обращение (запись/чтение) к QList.
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Очереди, самодельные сигналы
«
Ответ #95 :
Август 19, 2010, 21:02 »
Цитата: labview от Август 19, 2010, 20:54
Что не так с мьютексом? С помощью него я хотел защитить обращение (запись/чтение) к QList.
http://www.prog.org.ru/index.php?topic=14426.msg95492#msg95492
Записан
labview
Гость
Re: Очереди, самодельные сигналы
«
Ответ #96 :
Август 19, 2010, 21:16 »
Спасибо, теперь не ругается. А можно узнать почему? Пожалуйста.
Записан
BRE
Гость
Re: Очереди, самодельные сигналы
«
Ответ #97 :
Август 19, 2010, 21:43 »
Цитата: labview от Август 19, 2010, 21:16
Спасибо, теперь не ругается. А можно узнать почему? Пожалуйста.
Доступ к общим данным должен быть защищен.
Смотри что может произойти если ее не защитить:
управление получает первый поток и успевает выполнить проверку, что в очереди есть задания, после этого планировщик переключается на такой же поток, он успевает проверить, что в очереди есть данные и достать оттуда единственное значение. Сейчас очередь уже пуста, происходит переключение обратно на первый поток, он уже выполнил проверку на то, что в очереди есть задания и бросается его доставать, но очередь уже пуста.
Поэтому, даже чтение количества заданий должно быть защищено.
Почему происходила ошибка. Алгоритм работы условных переменных (QWaitCondition) сводится к тому, что вначале мы запираем мьютекс блокирующий данные, проверяем наличие данных, если в нем есть данные, то мы получаем к нему доступ (заметь, запертый мьютекс будет блокировать попытки других потоков добраться до этих данных), а если данных нет - то мы вызываем wait условной переменной связанной с этим мьютексом (указатель на него мы передаем в параметрах wait), wait открывает этот мьютекс (давая возможность другому потоку записать данные) и усыпляет поток.
Другой поток записывает данные и вызывает wakeOne/wakeAll, чем пробуждает поток(и) ждущие в wait. После пробуждения потока, в функции wait блокируется мьютекс и происходит выход из нее.
P.S. Разберись с QMutexLocker, подобные классы значительно облегчают работу с мьютексами и избавляют от ошибок.
«
Последнее редактирование: Август 19, 2010, 21:48 от BRE
»
Записан
labview
Гость
Re: Очереди, самодельные сигналы
«
Ответ #98 :
Август 19, 2010, 22:33 »
Благодарю за разяснение, пока сделал так:
Код:
task Tasking::getTask()
{
QMutexLocker locker(&mutex);
while(taskList.empty())
cond.wait(&mutex, ULONG_MAX);
return taskList.takeFirst();
}
void Tasking::addTask(task newTask)
{
QMutexLocker locker(&mutex);
taskList.append(newTask);
cond.wakeOne();
}
ЗЫ с ответами какашко получилось, сори, я стёр свой предыдущий ответ.
«
Последнее редактирование: Август 19, 2010, 22:35 от labview
»
Записан
labview
Гость
Re: Очереди, самодельные сигналы
«
Ответ #99 :
Август 23, 2010, 16:06 »
Привет!
Появилась новая проблема. Сначала я запускал в main два потока и потом QApplication::exec(). Но ивенты не обрабатывались и окно не прорисовывалось, т.к. QApplication::exec() был блокирован двумя потоками. Немного поразмыслив, я решил запустить третью нить, в функции run() которой, я собирался выполнить QApplication::exec(), то есть запустить главный поток параллельно двум другим.
При старте прога зависает и пишет QApplication::exec: Must be called from the main thread.
А как же мне ещё сделать обработку параллельно?
Выкладываю main.cpp
Код:
#include <QList>
#include "mainwidget.h"
#include "Tasking.h"
#include "guithread.h"
#include "thread1.h"
#include "thread2.h"
int main(int argc, char *argv[])
{
QList<Tasking*> allTasks;
Tasking *tasking1 = new Tasking;
Tasking *tasking2 = new Tasking;
allTasks.append(tasking1);
allTasks.append(tasking2);
GUIThread guiThread(allTasks, argc, argv);
Thread1 myThread1(allTasks);
Thread2 myThread2(allTasks);
QObject::connect(&myThread1, SIGNAL(showData(QString)), guiThread.w, SLOT(addText(QString)));
QObject::connect(&myThread2, SIGNAL(showData(QString)), guiThread.w, SLOT(addText(QString)));
guiThread.start();
myThread1.start();
myThread2.start();
guiThread.wait();
myThread1.wait();
myThread2.wait();
return 0;
}
guithread.cpp
Код:
#include "guithread.h"
GUIThread::GUIThread(const QList<Tasking*>& allTasks, int argc, char *argv[])
{
Tasks = allTasks;
qapp = new QApplication(argc, argv);
w = new MainWidget(Tasks);
w->showMW();
}
void GUIThread::run()
{
qapp->exec();
}
Ну и на всякий случай код потока (второй сделан аналогично)
Код:
#include "thread1.h"
Thread1::Thread1(const QList<Tasking*>& allTasks)
{
Tasks = allTasks;
}
void Thread1::run()
{
task myTask;
bool exit = FALSE;
while(!exit)
{
myTask = Tasks[0]->getTask();
switch (myTask.tasknum)
{
case 0:
exit = TRUE;
case 1:
emit showData(myTask.data);
Tasks[1]->addTask(myTask);
}
}
}
Спасибо!
Записан
BRE
Гость
Re: Очереди, самодельные сигналы
«
Ответ #100 :
Август 23, 2010, 16:32 »
QApplication::exec: Must be called from the main thread
это обязательное условие. Нельзя работать с GUI в других потоках, только главный.
Вызывай exec() в функции main().
А вот ожидать завершения дочерних потоков после старта не нужно (убери вызовы wait()).
Записан
labview
Гость
Re: Очереди, самодельные сигналы
«
Ответ #101 :
Август 23, 2010, 16:38 »
Спасибо, Вы так имели в виду?
Код:
myThread1.start();
myThread2.start();
qapp.exec();
myThread1.wait();
myThread2.wait();
Записан
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Очереди, самодельные сигналы
«
Ответ #102 :
Август 23, 2010, 16:44 »
Цитата: labview от Август 23, 2010, 16:06
Сначала я запускал в main два потока и потом QApplication::exec(). Но ивенты не обрабатывались и окно не прорисовывалось, т.к. QApplication::exec() был блокирован двумя потоками.
Не должен он быть блокирован, на то они и нитки чтобы выполняться параллельно
Цитата: labview от Август 23, 2010, 16:38
Код:
myThread1.start();
myThread2.start();
qapp.exec();
myThread1.wait();
myThread2.wait();
Да, это правильно и используется в большинстве случаев
Записан
BRE
Гость
Re: Очереди, самодельные сигналы
«
Ответ #103 :
Август 23, 2010, 16:51 »
Цитата: labview от Август 23, 2010, 16:38
Спасибо, Вы так имели в виду?
Скорее всего ты будешь останавливать свои потоки в какой то другой функции (когда они будут не нужны), вот там вызов wait() будет более уместен.
Записан
labview
Гость
Re: Очереди, самодельные сигналы
«
Ответ #104 :
Август 23, 2010, 16:55 »
Ура!!! Всё получилось, работает как я и ожидаю!
Огромнейшее спасибо Вам!
Выкладываю рабочий проект на Ваш просмотр.
Записан
Страниц:
1
...
5
6
[
7
]
8
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...