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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Сигналы и слоты + QThread + Qt 4.1.0 под Винду  (Прочитано 8742 раз)
Guk
Гость
« : Август 09, 2006, 16:47 »

Доброго времени суток!

Не могу найти свои грабли. Суть вот в чем:

есть класс

Код:

class ModemService :public QThread{
Q_OBJECT
public:
void run();
ModemService(QObject *parent);
public slots:
void WriteModem(QString Message);
        ...
signals:
void ReadModemData(QString DataString);
        ...
private:
        ...
};


Экземпляр этого класса создается динамически вот так вот:

Код:
MS = new ModemService(this);


Далее коннектим сигналы со слотами:

Код:
connect(MS,SIGNAL(ReadModemData(QString )),this,SLOT(GetFromModem(QString )),Qt::QueuedConnection);
connect(this,SIGNAL(SendToModem(QString )),MS,SLOT(WriteModem(QString )),Qt::QueuedConnection);
connect(MS, SIGNAL(finished()), MS, SLOT(deleteLater()),Qt::QueuedConnection);


а затем

Код:

MS->start();


что в теории должно вызвать вот этот метод

Код:
void ModemService::run(){

exec();
}


По теории - все. создали объект, зацепили сигналы со слотами, и вызвали run(). У нас есть поток, и мы можем с ним работать с помощью сигналов.
Поток действительно создается, сигналы работают. Только вот при зависании этого потока виснет всё приложение. Даже если сделать внутри любого слота потока вызов метода sleep(TimeVal) а затем послать ему соответствующий сигнал, на TimeVal замрет всё приложение, а не один только поток.
Никак не могу заметить в чем я не прав. Хелп плиз...
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #1 : Август 09, 2006, 17:28 »

добавь  sleep(1) попробуй
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Guk
Гость
« Ответ #2 : Август 10, 2006, 11:10 »

Цитата: "Racheengel"
добавь  sleep(1) попробуй


Добавил. (а зачем правда?). Всё приложение засыпает на 1 секунду. Хотя, в теории должен заснуть только один поток, в котором sleep я вызываю.
Вобщем суть в том, что мои создаваемые потоки должны обрабатывать ввод/вывод. При этом они могут подвисать на пару секунд (когда пишем в ком порт, а к нему ничего не приконектено). Если делать все из основного потока приложения, то подвисает весь интерфейс, поэтому вызовы чтения-записи я вынес в отдельные потоки. Но все равно подвисает всё приложение (пока "виснет" дочерний поток, главный (GUI-шный) поток приложения находится в состояниях: Wait:DelayExecution, потом Wait:Execution, а потом всё отвисает и все потоки, естественно, находятся в Wait:UserRequest )

Я понимаю, что просто неправильно объявил свой класс потока. Только вот не могу найти где я не прав. Или может все гораздо глубже...
Записан
dont
Гость
« Ответ #3 : Август 10, 2006, 12:23 »

Так, насколько я понял, то класс - это не поток, отдельный поток - эт все что в ф-ии run(). Попробуй весь свой код локализировать в энтом методе... Думаю тебе это поможет.
Записан
Guk
Гость
« Ответ #4 : Август 10, 2006, 12:53 »

Цитата: "dont"
...отдельный поток - эт все что в ф-ии run(). Попробуй весь свой код локализировать в энтом методе...


Гуд. Сенкс - уже начал переписывать. Проверю и расскажу. Только вот терзают меня сомнения. Вот какие:

Если ::run() отделяется в отдельный поток, то в нем мне нужно организовать бесконечный цикл, а уже в нем обработку всего что меня может интересовать. С другой стороны, чтоб задействовать механизм сигналов, мне нужно вызвать функцию exec(), из которой я вернусь только по завершению потока.
Итого, если тело run() будет выглядеть примерно так:

Код:
for (;;){
...}
exec()


то до вызова exec() дело естественно не дойдет.
А если

Код:
exec()
for (;;){
...
}


то до полезного цикла управление дойдет только по завершению потока...

Сейчас буду пробовать как-то выкрутиться.
Спасибо за идею Подмигивающий
Записан
dont
Гость
« Ответ #5 : Август 10, 2006, 13:52 »

Можешь попробывать заменить цикл таймером.
Записан
Guk
Гость
« Ответ #6 : Август 10, 2006, 15:40 »

Интересный диалог нашел на одном форуме. Видать не один я столкнулся с данной проблемкой. Только они там не с той стороны к ней подошли. Если есть желание - вот ссылка
http://www.qtcentre.org/forum/f-qt-programming-2/t-workload-in-a-qthread-blocks-main-applications-event-loop--1318.html
и в самом конце темы очень интересный комментарий:

Цитировать
Try this

Код:
otherThread = new OtherThread(this);
otherThread->moveToThread(otherThread);
otherThread->start();


that should work ... Regards Madrich


Попробую - расскажу...

добавлено спустя 52 минуты:

 Вот результат экспериментов:

вышеприведенный код с moveToThread не сработал - вот такой вот ASSERT:
Цитировать
Failure in QObject::moveToThread: "Cannot move objects with a parent"

Само собой сразу же поставил что-то аля вот так:

Код:
otherThread = new OtherThread(NULL);
//тут делаем коннект сигналам
otherThread->moveToThread(otherThread);
otherThread->start();
//а тут уже можно обращаться к потоку сигналами!!!!!


Странно, но код вполне рабочий. Может меня еще ждут по этому поводу сюрпризы, но на 10-ти минутах тестов отработал все возможные связи со своим потоком - все работает.
Спасибо всем - вопрос снят (надеюсь баги в этом коде уже не полезут  :wink: )
Записан
dont
Гость
« Ответ #7 : Август 11, 2006, 10:07 »

"вышеприведенный код с moveToThread не сработал - вот такой вот ASSERT:

Цитата:   
Failure in QObject::moveToThread: "Cannot move objects with a parent""

Наверное из-за этого:

"void QObject::moveToThread ( QThread * targetThread )
Changes the thread affinity for this object and its children. The object cannot be moved if it has a parent."
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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