Russian Qt Forum

Qt => Общие вопросы => Тема начата: foxexe от Январь 13, 2010, 19:04



Название: QThread генерирует ошибку до начала выполнения
Отправлено: foxexe от Январь 13, 2010, 19:04
Я совсем уже опустил руки, создаю классический каркас для треда
Код:
class MyThread: public QThread
{
public
        void run();
};
void MyThread::run()
{
             ....
             exec();
}


запуская такой тред в различных местах программы получаются разные Debugger error со страшными словами типа ASSET и прочее, ну иногда можно добиться вывода такой ошибки QThread: Destroyed while thread is still running
хотя тред то ещё даже не исполнил не одной строчки из своей функции.

Я конечно очень криво написал, но я честно вообще не понимаю что происходит. у меня такая странная догадочка что тред уничтожается или как-нить неправильно инициаллизируется, всё это происходит при вызове start();

даже запуск такого треда в фукции main  даёт ошибки, но уже что QWidget должет создаваться только в gui треде.

Qt 4.4.3 VS2008


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: Dendy от Январь 13, 2010, 19:07
Покажите как вы создаёте экземпляр этого потока.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: foxexe от Январь 13, 2010, 19:11
пробовал 2 варианта
Код:
MyThread a;
a.start();

Код:
MyThread *a=new MyThread();
a->start();

если создать пустой проект то такие штуки работают.

даже добавид CONFIG += thread хотя это я понимаю не особо важно


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: Dendy от Январь 13, 2010, 19:25
Подозреваю, что тред создаётся и запускает run() в другом потоке раньше, чем в вызывающем доходит до конца области видимости. Потом вызывается деструктор потока, в то время как его клавный цикл exec() не был остановлен. По умолчанию ~QThread() его сам не останавливает, поскольку это не гарантирует, что run() завершился корректно - ведь после exec() может быть ещё клиентский код. Вот он и ругается, что поток был прерван с возможными ошибками. Не было бы exec() - всё было бы так же печально, но с отличием, что ~QThread() не смог бы определить, выполняется ли ещё поток или нет. Отловить поведение собственного потока можно только самостоятельно в деструкторе, отправив циклу событий quit() и подождав, пока поток завершится с помощью wait().


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: foxexe от Январь 13, 2010, 19:47
Да спасибо, это кстати очень классная догадка, я бы недодумался , но я там всё же создавал по ссылке изначально, на самом деле он ругается что я пользуюсь объектом из другого потока что-ли. я вообще не особо понимаю в чём проблема, просто помню была такая ошибочка, вылезала, и правда убрал все вызовы  лишние работает, только вот как же теперь обратиться к объектам созданным в главном потоке


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: Dendy от Январь 13, 2010, 19:52
Непонятно откуда и к чему вы хотите обратиться.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: foxexe от Январь 13, 2010, 20:08
да я кстати щас вот думал как переформулировать и тут такое дело, что в основном потоке создаётся класс Engine, который собственно движок. и вот я в его конструкторе(в отлажочных целях) создаю поток, и обращаюсь к Engine по глобальной ссылке.

main.cpp
Код:
MyEngine *Engine
int main()
{
...
Engine= new MyEngine(...);
...
}


thread.cpp
Код:
extern MyEngine * Engine
MyThread::run()
{
         Engine->method();//вот где собака зарыта
}

у меня сейчас спутанность сознания какая-то и я вобщем вижу что есть в этом кривизна, но в чём именно не пойму.

получается что мне надо общать с этим Engine через сигнал-слоты?



Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: Dendy от Январь 13, 2010, 20:36
Можно общаться как и сейчас, только гарантировать:

1) Что обьект Engine будет существовать во время обращения к нему.
2) Потокобезопастность метода MyEngine::method().


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: foxexe от Январь 13, 2010, 20:56
ну Engine да создан, но method() просто запускает  QTextEdit::append() мне не кажется что это настолько потоконебезопасно, я попробую попозже там мютексы поставить, но что-то мне кажется не в этом то дело.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: Dendy от Январь 13, 2010, 21:00
Этот метод не может быть потокобезопастрым, поскольку QTextEdit::append() уже не reentrant. Его можно вызывать только из главного потока.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: foxexe от Январь 13, 2010, 21:19
так вот гда собака то зарыта!!! ес

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


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: Dendy от Январь 13, 2010, 21:33
Race Condition стало быть с непредсказуемыми последствиями.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: foxexe от Январь 13, 2010, 21:45
Пока не забыл, очень очень очень  огромное спасибо, помог и заставил меня думать.

точно точно, отсюда и постоянно разные ошибки, в разных файлах в разных местах
я так понимаю что гонка может произойти при условии что остальные потоки не запускают QTextEdit::append(), внутреняя архитектура тоесть там что-то там-то. А всё-таки как мне обращаться в этим method() тогда, через сигналослоты?

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


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: Dendy от Январь 13, 2010, 21:53
От сигналов-слотов в потоке вы всё равно не денетесь, другое дело что они будут выполняться в том же потоке, в котором этот сокет существует. По поводу вызова QTextEdit::append() - нужно как-то вот так выкрутиться, чтобы вызывать этот метод из главного потока. Например, вызвать в главном потоке слот с помощью Qt::BlockingQueuedConnection.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: foxexe от Январь 13, 2010, 22:01
всё раскручивается, это значит изначально неправильно, сокет то в главном потоке создаётся, а это возможно подобные проблемы. те либо его сразу в новый потом и там уже чё-нить делать, либо как-нить по другому, со стороны сервера это ещё куда ни шло такой расклад, но клиет с одним сокетом глуповато, да. Ну лан спасибо за информацию про блокед коннекш тоже почитаю, вообщем буду аккуратней с потоками, я просто до этого работал с ними на более банальном уровне только.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: Dendy от Январь 13, 2010, 22:04
Принадлежность к потоку обьектов вообще и сокета в частности определяется тем, в что этом потоке будут дёргаться виртуальный метод QObject::event(). Создавайте сокет внутри своего run() - это сделает его принадлежащим потоку, которому этот run() принадлежит.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: foxexe от Январь 13, 2010, 22:18
ну да значит я всё правильно думаю, спасибо огромное

смотря на тему становится даже немного стыдно)


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: Dendy от Январь 13, 2010, 22:24
Да ладно, работа с потоками - то ещё болото. И никакая теория не будет полноценной, пока сам в нём не искупаешься.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: BlackTass от Январь 13, 2010, 22:28
можно создавать и в конструкторе, главное только потом перенести с помощью метода moveToThread() (метод класса QObject). Вызывать его надо из того потока, где был создан объект. И не забудьте объект самого потока перенести в этот поток.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: Dendy от Январь 13, 2010, 22:36
И не забудьте объект самого потока перенести в этот поток.

Сильно сомнительный подход, от которого больше проблем. Лучше так не делать. Как минимум события потока, а следовательно и слоты, не будут обрабатываться до и после exec().


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: foxexe от Январь 13, 2010, 22:40
Да ладно, работа с потоками - то ещё болото. И никакая теория не будет полноценной, пока сам в нём не искупаешься.
да это я абсолютно согласен. Мне хватило даже институтских прог сначала винда, потом соляра, и там эти вещи побезопасней для потоков сделаны вроде.


можно создавать и в конструкторе, главное только потом перенести с помощью метода moveToThread() (метод класса QObject). Вызывать его надо из того потока, где был создан объект. И не забудьте объект самого потока перенести в этот поток.
очень хорошо подмечено, я и забыл про moveToThread(). однако это не решает моей архитектурной проблемы обработки приёма и отправки в разных потоках. ладно буду думать что тут делать.
А зачем мне переносить объект потока к себе в поток?


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: BlackTass от Январь 13, 2010, 22:45
Сильно сомнительный подход, от которого больше проблем. Лучше так не делать. Как минимум события потока, а следовательно и слоты, не будут обрабатываться до и после exec().
ну после exec() в большинстве случаев наступает смерть потока.

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

Хотя вы правы, я погорячился советовать это делать всегда. Нужно понимать к чему приведет такое и для чего это нужно.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: Dendy от Январь 13, 2010, 22:55
А зачем мне переносить объект потока к себе в поток?

Как правило в run() создаётся нечто, что будет там жить и ловить события. Поток засовывают сам в себя когда лень создавать новый класс-обработчик, наследник QObject. Однако такой подход рвёт всё управление событиями/слотами экземпляром потока извне и влечёт ошибки на пустом месте. Технически никакого преимущества, кроме того, что два класса смешаны в один. И да, фильтр событий тоже не будет работать между потоками, зачем так сделано в Qt мне непонять.


Название: Re: QThread генерирует ошибку до начала выполнения
Отправлено: BlackTass от Январь 13, 2010, 23:59
Однако такой подход рвёт всё управление событиями/слотами экземпляром потока извне и влечёт ошибки на пустом месте. Технически никакого преимущества, кроме того, что два класса смешаны в один.

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