Russian Qt Forum

Qt => Общие вопросы => Тема начата: Guk от Август 09, 2006, 16:47



Название: Сигналы и слоты + QThread + Qt 4.1.0 под Винду
Отправлено: 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 замрет всё приложение, а не один только поток.
Никак не могу заметить в чем я не прав. Хелп плиз...


Название: Сигналы и слоты + QThread + Qt 4.1.0 под Винду
Отправлено: Racheengel от Август 09, 2006, 17:28
добавь  sleep(1) попробуй


Название: Сигналы и слоты + QThread + Qt 4.1.0 под Винду
Отправлено: Guk от Август 10, 2006, 11:10
Цитата: "Racheengel"
добавь  sleep(1) попробуй


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

Я понимаю, что просто неправильно объявил свой класс потока. Только вот не могу найти где я не прав. Или может все гораздо глубже...


Название: Сигналы и слоты + QThread + Qt 4.1.0 под Винду
Отправлено: dont от Август 10, 2006, 12:23
Так, насколько я понял, то класс - это не поток, отдельный поток - эт все что в ф-ии run(). Попробуй весь свой код локализировать в энтом методе... Думаю тебе это поможет.


Название: Сигналы и слоты + QThread + Qt 4.1.0 под Винду
Отправлено: Guk от Август 10, 2006, 12:53
Цитата: "dont"
...отдельный поток - эт все что в ф-ии run(). Попробуй весь свой код локализировать в энтом методе...


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

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

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


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

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


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

Сейчас буду пробовать как-то выкрутиться.
Спасибо за идею ;)


Название: Сигналы и слоты + QThread + Qt 4.1.0 под Винду
Отправлено: dont от Август 10, 2006, 13:52
Можешь попробывать заменить цикл таймером.


Название: Сигналы и слоты + QThread + Qt 4.1.0 под Винду
Отправлено: Guk от Август 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: )


Название: Сигналы и слоты + QThread + Qt 4.1.0 под Винду
Отправлено: dont от Август 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."