Название: Объясните! ) Как тело функции запускается несколько раз в одном и том же потоке Отправлено: r2d2u2 от Ноябрь 10, 2010, 01:46 В общем есть Объект класса унаследованного от QThread.
Дергаем метод Start() у этого объекта несколько раз подряд. Исполнение этого метода запускается в отдельном потоке. Несколько раз. Подряд. Причем следующий вызов не ожидает завершения предыдущего. При этом когда этот метод запускается в то время когда выполняется исполнение предыдущего вызова, !все в том же потоке! то предыдущий вызов никуда не девается а как бы попадает в стек, и ждет пока завершится последний вызов потом возобновляется. Вот классы чтобы самим не писать соберите консольное приложение и потыкайте кнопкой несколько раз: у меня вывод вот такой: ThreadObject::ThreadObject(): 0x9c 0 ThreadObject::run(): 0x4a0 0 ThreadObject::StartTimer(): 0x4a0 0 ThreadObject::StartTimer(): 0x4a0 1 ThreadObject::StartTimer(): 0x4a0 2 ThreadObject::StartTimer(): stop 0x4a0 3 ThreadObject::StartTimer(): stop 0x4a0 3 ThreadObject::StartTimer(): stop 0x4a0 3 class ThreadObject: public QThread { Q_OBJECT public: ThreadObject(); virtual ~ThreadObject(); public slots: void Start(); public: void run(); int Var; }; ThreadObject::ThreadObject() { moveToThread(this); Var = 0; qDebug() << "ThreadObject::ThreadObject(): " << currentThreadId() << Var; } ThreadObject::~ThreadObject() { quit(); wait(); } void ThreadObject::run() { qDebug() << "ThreadObject::run(): " << currentThreadId() << Var; exec(); } void ThreadObject::Start() { qDebug() << "ThreadObject::StartTimer(): " << currentThreadId() << Var; ++Var; for (qint64 i = 0; i < 500000; ++i) { QCoreApplication::processEvents(QEventLoop::AllEvents, 1); } qDebug() << "ThreadObject::StartTimer(): stop" << currentThreadId() << Var; } class MyWidget: public QWidget { Q_OBJECT public: MyWidget(QWidget* parent = 0); void Create(); void Layout(); void Connect(); void StartThread(); private: QPushButton* Button; ThreadObject TheThreadObject; }; MyWidget::MyWidget(QWidget* parent /*= 0*/) : QWidget(parent) { Create(); Layout(); Connect(); StartThread(); } void MyWidget::Create() { Button = new QPushButton("QPush button"); } void MyWidget::Layout() { QHBoxLayout* mainLayout = new QHBoxLayout(); mainLayout->addWidget(Button); setLayout(mainLayout); } void MyWidget::Connect() { connect(Button, SIGNAL(clicked()), &TheThreadObject, SLOT(Start())); } void MyWidget::StartThread() { TheThreadObject.start(); } ну и main int main(int argc, char **argv) { setlocale(LC_CTYPE, ""); bool useGUI = true; QApplication app(argc, argv, useGUI); MyWidget mWidget; mWidget.show(); return app.exec(); } Есть какие либо мысли и соображения? Если вызвать метод Start() первый раз, начнет выполняться цикл в потоке TH01, и к примеру счетчик i дойдет до 1024. Потом мы дергаем это метод Start() второй раз, и он запускается снова в потоке TH01! и счетчик начинает считать снова с нуля. НО! когда после второго вызова счетчик доходит до предела, выход из метода не происход а возобновляется работа счетчика запущенного при вызове метода в первый раз, т.ею начинается дальше счет с 1024. Кто нить может объяснить как такое может быть? ) Понятное дело что там в теле цикла стоит вызов QCoreApplication::processEvents(QEventLoop::AllEvents, 1); который обеспечивает обработку событий в том числе обрабатывает обработку события на второй вызов этого метода Start() в то время как предыдущий вызов еще не завершился. Но как смешивается работа циклов непонятно такое ощущение, что при следующем вызове, текущий цикл помещается куда то в стек откуда потом вытаскивается. кстати QCoreApplication::processEvents(QEventLoop::AllEvents, 1); вызывается внутри функции void QTest::qWait ( int ms ), так что если вы вставите себе этот qWait в теле функции f()работающей в отдельном потоке то при вызове qWait внутри f() она пропусти все события-вызовы f() и ваша f() вызовится несколько раз в одном потоке, и если так мьютекс был рекурсивный то беда! _ Название: Re: Объясните! ) Как тело функции запускается несколько раз в одном и том же потоке Отправлено: BlackTass от Ноябрь 10, 2010, 02:14 По моему все вполне логично :) метод запускается еще раз с начала во время процессЕвентс. Когда он доходит до конца процессЕвентс возвращается к выполнению предыдущего запуска этого метода (из которого был вызван этот самый процессЕвентс)
Название: Re: Объясните! ) Как тело функции запускается несколько раз в одном и том же потоке Отправлено: DmP от Ноябрь 10, 2010, 12:05 В общем есть Объект класса унаследованного от QThread. Зачем его дергать несколько раз подряд? Дергаем метод Start() у этого объекта несколько раз подряд. Исполнение этого метода запускается в отдельном потоке. Несколько раз. Подряд. Причем следующий вызов не ожидает завершения предыдущего. В отдельном ли?Название: Re: Объясните! ) Как тело функции запускается несколько раз в одном и том же потоке Отправлено: r2d2u2 от Ноябрь 10, 2010, 20:01 По моему все вполне логично :) метод запускается еще раз с начала во время процессЕвентс. Когда он доходит до конца процессЕвентс возвращается к выполнению предыдущего запуска этого метода (из которого был вызван этот самый процессЕвентс) вообщето да, получается вроде рекурсивного вызова себя самой только почему переменная Var как бы разделяется всеми рекурсивными вызовами и увеличивается при каждом вызове а цикл начинается с начала. :) Название: Re: Объясните! ) Как тело функции запускается несколько раз в одном и том же потоке Отправлено: r2d2u2 от Ноябрь 10, 2010, 20:12 В общем есть Объект класса унаследованного от QThread. Зачем его дергать несколько раз подряд? Дергаем метод Start() у этого объекта несколько раз подряд. Исполнение этого метода запускается в отдельном потоке. Несколько раз. Подряд. Причем следующий вызов не ожидает завершения предыдущего. В отдельном ли?Зачем дергать несколько раз подряд? Ну к примеру эта функция вызывается другими потоками и может так получится что она вызовется несколько раз подряд. Это в общем на конкретные названия и смысл смотреть не нужно. Это пример. А запускается действительно в отдельном. Я и сам не пойму почему так получается. Если в конструкторе ThreadObject() вызвать moveToThread(this); то вызов ThreadObject::Start() запускается в отельном потоке. Если в конструкторе не вызывать moveToThread(this) то вызов ThreadObject::Start() запускается в том же потоке откуда вызывается. Вот тоже непонятно почему? Допустим конструктор ThreadObject() вызывается в главном потоке, и сам объект ThreadObject принадлежит главному потоку, и если в конструкторе вызвать moveToThread(this); то по идее это есть "перемещение" объекта ThreadObject в свой же главный поток. т.е. обработка событий по вызову слотов этого объекта будет осуществляться в главном потоке, по идее смысла от этого нет никакого как мне кажется, но после этого методы объекта ThreadObject вызываются в созданном этим объектом потоке. Вот как понять? Название: Re: Объясните! ) Как тело функции запускается несколько раз в одном и том же потоке Отправлено: BRE от Ноябрь 10, 2010, 20:21 А ты по форуму поищи темы по moveToThread, уже несколько раз обсуждали, что делает вышеуказанная конструкция и про типы connect, и про очереди сообщений...
Название: Re: Объясните! ) Как тело функции запускается несколько раз в одном и том же потоке Отправлено: DmP от Ноябрь 10, 2010, 20:42 А запускается действительно в отдельном. Я и сам не пойму почему так получается. Если в конструкторе ThreadObject() вызвать moveToThread(this); то вызов ThreadObject::Start() запускается в отельном потоке. Если в конструкторе не вызывать moveToThread(this) то вызов ThreadObject::Start() запускается в том же потоке откуда вызывается. Вот тоже непонятно почему? На самом деле тут все просто.Допустим конструктор ThreadObject() вызывается в главном потоке, и сам объект ThreadObject принадлежит главному потоку, и если в конструкторе вызвать moveToThread(this); то по идее это есть "перемещение" объекта ThreadObject в свой же главный поток. т.е. обработка событий по вызову слотов этого объекта будет осуществляться в главном потоке, по идее смысла от этого нет никакого как мне кажется, но после этого методы объекта ThreadObject вызываются в созданном этим объектом потоке. Вот как понять? moveToThread(this) - приписывает объект потока в обработчик потока (как и говорится в документации). При каждом нажатии на кнопку, сигнал помещается в очередь обработчика потока (а не вызывается напрямую, так как потоки разные). Первый раз ThreadObject::Start() вызывается обработчиком событий потока, который запущен в void ThreadObject::run() через exec(). Все последующие разы ThreadObject::Start() вызывает сам себя, передавая управление обработчику событий через QCoreApplication::processEvents(). Название: Re: Объясните! ) Как тело функции запускается несколько раз в одном и том же потоке Отправлено: r2d2u2 от Ноябрь 10, 2010, 22:08 DmP сапасиба! :D
|