Russian Qt Forum

Qt => Общие вопросы => Тема начата: ymb от Февраль 26, 2010, 16:41



Название: Передача значения в главный поток. (Qt 4.6)
Отправлено: ymb от Февраль 26, 2010, 16:41
есть дополнительный поток
mytask.h
Код:
...
class MyTask: public QThread
{
Q_OBJECT
protected:
    void run();
signals:
    void mymess(int);
private:
    int N;

};
...
mytask.cpp
Код:
...
extern bool FlagStop;

void MyTask::run()
{
    QString S;

    N=0;
    do {
        if (FlagStop == 1) {
            break;
        }
        msleep(500);
        emit mymess(N);
        N++;
    }
    while (N<1000);
}
...

в главном потоке:
Код:
...
connect(task,SIGNAL(mymess(int)),this,SLOT(PrintMess()));
...
1. Как достать N из mymess?
2. FlagStop - глобальная переменная. Надо ли её блокировать при чтении и записи?
3. Можно ли обойтись без глобальных переменных?     


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: Akaiten от Февраль 26, 2010, 17:48
1. Объявить в PrintMess() параметр типа int, через который и будет передаваться значение N (не забудь изменить SLOT() в connect);
2. В потоке MyTask ты её только читаешь, из другого потока только меняешь, поэтому можно не блокировать;
3. Сделать её членом класса MyTask и добавить метод типа
Код
C++ (Qt)
void MyTask::abort()
{
 /*this->*/FlagStop = 1;
}
 


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: pastor от Февраль 26, 2010, 18:32
2. В потоке MyTask ты её только читаешь, из другого потока только меняешь, поэтому можно не блокировать;

Неверно, блокировать нужно, это не атомарная операция. Может наступить момент когда будет производиться одновременная запись и чтение переменной.


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: Igors от Февраль 26, 2010, 18:50
Неверно, блокировать нужно, это не атомарная операция. Может наступить момент когда будет производиться одновременная запись и чтение переменной.
Ну я бы не сказал что "неверно" - просто надо иметь ввиду что установка FlagStop = 1 не прекратит вычисления в нитке немедленно, он может прокрутить еще 1 итерацию (а то и 2). Например PrintMess может быть вызван уже после установки. Если "нужны гарантии" - надо блокировать.


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: pastor от Февраль 26, 2010, 20:23
Если "нужны гарантии" - надо блокировать.

А кому ненужны гарантии? ))) На авось лучше не полагаться


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: SABROG от Февраль 27, 2010, 01:20
Если "нужны гарантии" - надо блокировать.

А кому ненужны гарантии? ))) На авось лучше не полагаться

Студентам, которые сдали лабораторную и пошли пиво пить.


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: BRE от Февраль 27, 2010, 09:57
А вот это определение:
void PrintMess(int K);

находиться в секции
... slots:
?

Код
C++ (Qt)
class MainWindow : ...
{
...
protected slots:
void PrintMess(int K);
};
 


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: ymb от Февраль 27, 2010, 10:32
Код:
private slots:
    void PrintMess(int K);
connect
Код:
connect(task,SIGNAL(mymess(int)),this,SLOT(PrintMess(int)));
теперь работает.



  
 


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: ymb от Февраль 27, 2010, 10:45
Ещё вопросы:
1. Что лучше?
    а) передавать сигнал завершения доп.потока через глобальную переменную;
    б) с помощью сигналов и слотов;

2. Будет ли корректно обрабатываться сигнал из главного потока в доп.поток, если в доп.потоке крутиться свой цикл?   


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: Akaiten от Февраль 27, 2010, 14:09
1. Я считаю однозначно через открытую функцию класса (в частности через слот). Что если завтра тебе понадобится два потока вместо одного?
2. Смотря какой цикл и тип соединения сигнала-слота :). Если используется DirectConnection, то слот будет выполняться в контексте главного потока и ему будет пофиг что делает доп. поток, а, если QueuedConnection (BlockingQueuedConnection), то чтобы слот вызвался, в доп. потоке должен крутиться QEvenLoop.


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: Igors от Февраль 27, 2010, 18:33
1. При работе с нитками глобальных переменных нужно избегать всем доступными средствами
2. Смотря какой цикл и тип соединения сигнала-слота :). Если используется DirectConnection, то слот будет выполняться в контексте главного потока и ему будет пофиг что делает доп. поток, а, если QueuedConnection (BlockingQueuedConnection), то чтобы слот вызвался, в доп. потоке должен крутиться QEvenLoop.
Если connect связывает 2 QObject созданных а разных нитках - то обмен сигнал/слот будет производиться только через QEvenLoop - и для DirectConnection тоже (просто вызывающий будет ждать пока событие принято из QEvenLoop приемника и обработано)


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: BRE от Февраль 27, 2010, 19:52
Если connect связывает 2 QObject созданных а разных нитках - то обмен сигнал/слот будет производиться только через QEvenLoop - и для DirectConnection тоже (просто вызывающий будет ждать пока событие принято из QEvenLoop приемника и обработано)
Ты уверен? Где про это написано?
Или ты про Qt::BlockingQueuedConnection?

Залез в документацию Qt 4.6.2, там конечно есть изменения, но про межпотоковый DirectConnection не нашел... ?
Constant               Value   Description
Qt::AutoConnection         0      (default) Same as DirectConnection, if the emitter and receiver are in the same thread. Same as QueuedConnection, if the emitter and receiver are in different threads.

Qt::DirectConnection      1      The slot is invoked immediately, when the signal is emitted.

Qt::QueuedConnection      2      The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.

Qt::BlockingQueuedConnection   4      Same as QueuedConnection, except the current thread blocks until the slot returns. This connection type should only be used where the emitter and receiver are in different threads. Note: Violating this rule can cause your application to deadlock.

Qt::UniqueConnection      0x80      Same as AutoConnection, but the connection is made only if it does not duplicate an existing connection. i.e., if the same signal is already connected to the same slot for the same pair of objects, then the connection will fail. This connection type was introduced in Qt 4.6.

Qt::AutoCompatConnection   3      The default type when Qt 3 support is enabled. Same as AutoConnection but will also cause warnings to be output in certain situations. See Compatibility Signals and Slots for further information.


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: ymb от Февраль 27, 2010, 21:02
Спасибо. Тут есть над чем подумать. Буду разбираться.


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: Igors от Февраль 28, 2010, 12:55
Если connect связывает 2 QObject созданных а разных нитках - то обмен сигнал/слот будет производиться только через QEvenLoop - и для DirectConnection тоже (просто вызывающий будет ждать пока событие принято из QEvenLoop приемника и обработано)
Здесь я был неправ (ошибся разбирая исходники). После критики BRE сделал тестовый примерчик (attachment) - да, все работает согласно документации, и вызов слота c DirectConnection происходит в нитке вызывающего.


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: brucemax от Март 20, 2013, 10:15
Парни..  а если я из другого потока, который принимает данные из сети,  сигналом  передаю их (константной ссылкой QByteArrayем) в главный поток, ничего плохого случиться не может?=)    То есть в сетевом потоке постоянно создаются объекты(не динамически), одно из полей которых (именно этот QByteArray) эмититься в главный поток..  Так вот правильна ли моя логика, если я буду передавать этот bytearray константной ссылкой, то может получиться нехорошо, так как этот объект убьётся в сетевом потоке (ибо так он создавался не динамически в блоке), а мой главный поток будет юзать ссылку на него в это время  ???


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: Kurles от Март 20, 2013, 11:47
Парни..  а если я из другого потока, который принимает данные из сети,  сигналом  передаю их (константной ссылкой QByteArrayем) в главный поток, ничего плохого случиться не может?=)    То есть в сетевом потоке постоянно создаются объекты(не динамически), одно из полей которых (именно этот QByteArray) эмититься в главный поток..  Так вот правильна ли моя логика, если я буду передавать этот bytearray константной ссылкой, то может получиться нехорошо, так как этот объект убьётся в сетевом потоке (ибо так он создавался не динамически в блоке), а мой главный поток будет юзать ссылку на него в это время  ???
Обсуждалось это (http://www.prog.org.ru/index.php?topic=23864.msg169026#msg169026) уже  :)


Название: Re: Передача значения в главный поток. (Qt 4.6)
Отправлено: brucemax от Март 20, 2013, 12:17
Обсуждалось это (http://www.prog.org.ru/index.php?topic=23864.msg169026#msg169026) уже  :)
Спасибо, друг! ;)