Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: QThread
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Общие вопросы
gpepsi
как из потоковой функции можно понять, что ожидается завершение потока ?
ViGOur
Послать ей сигнал.
Или ввести какую-нибудь переменную, например bool m_bThreadStop = false;, которую периодически проверять.
gpepsi
Цитата(ViGOur @ 5.10.2011, 11:00) *
Или ввести какую-нибудь переменную, например bool m_bThreadStop = false;, которую периодически проверять.


у меня куча потоков. для каждой заводить переменную ?

Цитата(ViGOur @ 5.10.2011, 11:00) *
Послать ей сигнал.


а как внутри определить ?

ну если внутри
while(true)
{
}

никак не завершиться. нужно ожидать на чем-то. Странно что этого не предусмотрели...
silver47
Цитата(gpepsi @ 5.10.2011, 14:34) *
у меня куча потоков. для каждой заводить переменную ?


Если Вам необходимо тормозить все потоки одновременно, то проще завести одну переменную в главном потоке, а остальным передать указатель на нее.

Чем не подходит QThread::quit() ?
gpepsi
Цитата(silver47 @ 5.10.2011, 14:53) *
Чем не подходит QThread::quit() ?


а как это будет выглядеть ?
gpepsi
Цитата(silver47 @ 5.10.2011, 14:53) *
Чем не подходит QThread::quit() ?


а - понял, что имеется ввиду
 class MyThread : public QThread
{
public:
     void run();
};

void MyThread::run()
{
     QTcpSocket socket;
     // connect QTcpSocket's signals somewhere meaningful
     ...
     socket.connectToHost(hostName, portNumber);
     exec();
}


в главном потоке
main()
{
   QCoreApplication app(...);
   MyThread th;
   ...
   app.exec();
   ...
   th.quit();
   th.wait();
   return 0;

}


1. Это если все на сигналах построено, а если мне нужно крутить цикл, например, для чтения
while(...)
{
   ReadFile(...);
}


2. Что если слоты подключаются в главном потоке, а сигналы вызываются в дочернем ?
silver47
Имеется ввиду, что если у вас есть указатели на потоки, то можно вызвать метод QThread::quit(). А проверить есть ли запущенные потоки, кроме основного и подождать их завершения можно так:
if(QThreadPool::globalInstance()->activeThreadCount()) QThreadPool::globalInstance()->waitForDone();


Крутить цикл для чтения из чего? Из файла или Вы серверную\клиентскую сторону сетевого приложения пишете? Во втором случае, удобнее, как мне кажется, использовать сигнал readyRead().
ViGOur
Цитата(gpepsi @ 5.10.2011, 13:34) *
у меня куча потоков. для каждой заводить переменную ?

Зачем для каждого? Достаточно разок завести для базового, что-то вроде этого:

class MyThread : public QThread
{
     bool m_bExit;
public:
     void run();
};

void MyThread::run()
{
     // ...
     while( !m_bExit)
     {
        // ...
        ReadFile(...);
     }
}

gpepsi
Цитата(ViGOur @ 6.10.2011, 10:01) *
Зачем для каждого? Достаточно разок завести для базового, что-то вроде этого:


а как тогда с циклом обработки событий быть, если он запускается через exec, а мне нужно, чтоб поток посылал сигналы.
ViGOur
Или выносить в другой поток или не использовать цикл, а пользоваться только сигналами...
gpepsi
Цитата(ViGOur @ 6.10.2011, 15:42) *
Или выносить в другой поток или не использовать цикл, а пользоваться только сигналами...


ну а если мне нужно и цикл крутить и сигналить ?
ViGOur
А ты попробуй.
Механизм сигналов и слотов асинхронный, если ты не будешь тупо всисеть в sleep в потоке, который должен получить сигнал, то значит всё долно работать.

И еще, как ты думаешь в твоём коде:
main()
{
   QCoreApplication app(...);
   MyThread th;
   ...
   app.exec();
   ...
   th.quit();
   th.wait();
   return 0;

}
дойдет выполнение до th.quit(); ?
Мне кажется, что дальше app.exec(); не пройдет. :)
gpepsi
Цитата(ViGOur @ 6.10.2011, 16:38) *
А ты попробуй.


а что тут пробовать
#include <QThread>

class Thread : public QThread {
    Q_OBJECT
private:
    virtual void run(void);

public :
    explicit Thread(QObject* parent) : QThread(parent) {}
    virtual ~Thread() {}

signals:
    void send(void);
};

class Owner : public QObject {
    Q_OBJECT
private:
    Thread m_thread;

    virtual void timerEvent ( QTimerEvent * event );

public :
    explicit Owner(QObject* parent = nullptr);
    virtual ~Owner() {}
    
public slots:
    void recv(void);
};


код
#include "main.h"
#include <QtCore/QCoreApplication>
#include <QDebug>

void Thread::run( void )
{
    forever
    {
        emit send();
        QThread::msleep(1000);
    }
}

Owner::Owner( QObject* parent /*= nullptr*/ ) : QObject(parent), m_thread(this)
{
    connect(&m_thread, SIGNAL(send()), this, SLOT(recv()));
    m_thread.start();

    startTimer(5000);
}

void Owner::recv( void )
{
    qDebug() << "received signal";
}

void Owner::timerEvent( QTimerEvent * event )
{
    m_thread.quit();
    m_thread.wait();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Owner owner;
    return a.exec();
}


без цикла обработки quit не прокатывает
ViGOur
Посмотри на: QCoreApplication::processEvents, он как раз делает то, что тебе нужно...
silver47
Цитата
void Thread::run( void )
{
    forever
    {
        emit send();
        QThread::msleep(1000);
    }
}


Зачем это? Что Вы делаете в цикле то?
gpepsi
Цитата(ViGOur @ 6.10.2011, 18:18) *
Посмотри на: QCoreApplication::processEvents, он как раз делает то, что тебе нужно...


бесконечный цикл он все-равно не сбросит, так что без флага не обойтись :(
silver47
Так всетаки зачем бесконечный цикл то? Мое мнение такое - если бесконечный цикл - то наследоваться от QThread нафиг не нужно - делаем обычный QtConcurrent
ViGOur
processEvents не сбрасывает ничего, а просто дает отработать сигналам для данного потока.
А если цикл не просто бесконечный, с условием, тогда всё в порядке.
gpepsi
Цитата(ViGOur @ 6.10.2011, 20:17) *
А если цикл не просто бесконечный, с условием, тогда всё в порядке.

то есть самому контролировать выход ?
Цитата(ViGOur @ 6.10.2011, 20:17) *
processEvents не сбрасывает ничего, а просто дает отработать сигналам для данного потока.

руками вместо exec ?

Цитата(silver47 @ 6.10.2011, 20:12) *
Так всетаки зачем бесконечный цикл то? Мое мнение такое - если бесконечный цикл - то наследоваться от QThread нафиг не нужно - делаем обычный QtConcurrent


а чем он лучше и как решит это мою проблему ?

P.S. и кстати как быть с сигналами. Если объект создан в главном потоке, то и сигналы в главном потоке будут обрабатываться, а если объект создан в run ?
ViGOur
Цитата
то есть самому контролировать выход ?
Да, именно так. у тебя же цикл не с вечным sleep'ом, вот и вызывай на каждой его итерации processEvents. А он в свою очередь будет обрабатывать сигналы и вызывать что нужно...

Цитата
руками вместо exec ?
Да. Выше уже описал...

Цитата
P.S. и кстати как быть с сигналами. Если объект создан в главном потоке, то и сигналы в главном потоке будут обрабатываться, а если объект создан в run ?
Запомни, в каком потоке создан объек, в том он и обрабатывается. Если тебя это не устраивает, то после создания объекта ты его можешь передать в другой поток с помощью: void QObject::moveToThread ( QThread * targetThread )
gpepsi
ViGOur, а если я создаю поток только для вычитывания и разбора данных. Далее я хочу разобранные данные отдать в GUI для отрисовки.
Получается, что в run я должен это все делать, а отдавать данные через сигнал. Если объект создан в главном потоке, то и сигнал будет
обработан в главном потоке, что позволит отрисовать их в GUI.
Причем processEvents будет не нужен, т.к. QCoreApplication::exec обрабатывает свой цикл событий.
Причем в данно случае я могу объекту потоку послать сигнал, который будет обработан в главном потоке.

Я правильно размышляю ?

Единственное остался вопрос - зачем тогда вообще создавать объекты в run как в примере
 class MyThread : public QThread
{
public:
     void run();
};

void MyThread::run()
{
     QTcpSocket socket;
     // connect QTcpSocket's signals somewhere meaningful
     ...
     socket.connectToHost(hostName, portNumber);
     exec();
}

если для GUI их все-равно придется отдавать в главный поток, что за нас делает сигнал

Кстати, если я не использую потоки, а только сигналы, например, вычитывая данные из сокета вся обработка будет в главном потоке, то приведет
к подвисанию GUI если данных очень много

P.S. А чем тогда QtConcurrent полезен ?
ViGOur
Чтобы было меньше вопросов, предлагаю тебе почитать вот что:
1. Поддержка потоков в Qt
2. Сигналы и слоты

Там не так много букв как кажется, и как показывает практика как хотелось бы, и это базовые знания, которые нужно знать каждому, кто работает с Qt и использует потоки. Ну а без сигналов тут разумеется никуда.

И если после прочтения у тебя возникнут вопросы, то задавай их, но я думаю они сами по себе отпадут. :)

QtConcurrent, там тоде описан...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.