Russian Qt Forum
Ноябрь 24, 2024, 14:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Передача значения в главный поток. (Qt 4.6)  (Прочитано 12890 раз)
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. Можно ли обойтись без глобальных переменных?     
Записан
Akaiten
Гость
« Ответ #1 : Февраль 26, 2010, 17:48 »

1. Объявить в PrintMess() параметр типа int, через который и будет передаваться значение N (не забудь изменить SLOT() в connect);
2. В потоке MyTask ты её только читаешь, из другого потока только меняешь, поэтому можно не блокировать;
3. Сделать её членом класса MyTask и добавить метод типа
Код
C++ (Qt)
void MyTask::abort()
{
 /*this->*/FlagStop = 1;
}
 
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #2 : Февраль 26, 2010, 18:32 »

2. В потоке MyTask ты её только читаешь, из другого потока только меняешь, поэтому можно не блокировать;

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

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Февраль 26, 2010, 18:50 »

Неверно, блокировать нужно, это не атомарная операция. Может наступить момент когда будет производиться одновременная запись и чтение переменной.
Ну я бы не сказал что "неверно" - просто надо иметь ввиду что установка FlagStop = 1 не прекратит вычисления в нитке немедленно, он может прокрутить еще 1 итерацию (а то и 2). Например PrintMess может быть вызван уже после установки. Если "нужны гарантии" - надо блокировать.
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #4 : Февраль 26, 2010, 20:23 »

Если "нужны гарантии" - надо блокировать.

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

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
SABROG
Гость
« Ответ #5 : Февраль 27, 2010, 01:20 »

Если "нужны гарантии" - надо блокировать.

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

Студентам, которые сдали лабораторную и пошли пиво пить.
Записан
BRE
Гость
« Ответ #6 : Февраль 27, 2010, 09:57 »

А вот это определение:
void PrintMess(int K);

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

Код
C++ (Qt)
class MainWindow : ...
{
...
protected slots:
void PrintMess(int K);
};
 
Записан
ymb
Гость
« Ответ #7 : Февраль 27, 2010, 10:32 »

Код:
private slots:
    void PrintMess(int K);
connect
Код:
connect(task,SIGNAL(mymess(int)),this,SLOT(PrintMess(int)));
теперь работает.



  
 
« Последнее редактирование: Февраль 27, 2010, 10:40 от ymb » Записан
ymb
Гость
« Ответ #8 : Февраль 27, 2010, 10:45 »

Ещё вопросы:
1. Что лучше?
    а) передавать сигнал завершения доп.потока через глобальную переменную;
    б) с помощью сигналов и слотов;

2. Будет ли корректно обрабатываться сигнал из главного потока в доп.поток, если в доп.потоке крутиться свой цикл?   
Записан
Akaiten
Гость
« Ответ #9 : Февраль 27, 2010, 14:09 »

1. Я считаю однозначно через открытую функцию класса (в частности через слот). Что если завтра тебе понадобится два потока вместо одного?
2. Смотря какой цикл и тип соединения сигнала-слота Улыбающийся. Если используется DirectConnection, то слот будет выполняться в контексте главного потока и ему будет пофиг что делает доп. поток, а, если QueuedConnection (BlockingQueuedConnection), то чтобы слот вызвался, в доп. потоке должен крутиться QEvenLoop.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Февраль 27, 2010, 18:33 »

1. При работе с нитками глобальных переменных нужно избегать всем доступными средствами
2. Смотря какой цикл и тип соединения сигнала-слота Улыбающийся. Если используется DirectConnection, то слот будет выполняться в контексте главного потока и ему будет пофиг что делает доп. поток, а, если QueuedConnection (BlockingQueuedConnection), то чтобы слот вызвался, в доп. потоке должен крутиться QEvenLoop.
Если connect связывает 2 QObject созданных а разных нитках - то обмен сигнал/слот будет производиться только через QEvenLoop - и для DirectConnection тоже (просто вызывающий будет ждать пока событие принято из QEvenLoop приемника и обработано)
Записан
BRE
Гость
« Ответ #11 : Февраль 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.
« Последнее редактирование: Февраль 27, 2010, 20:07 от BRE » Записан
ymb
Гость
« Ответ #12 : Февраль 27, 2010, 21:02 »

Спасибо. Тут есть над чем подумать. Буду разбираться.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Февраль 28, 2010, 12:55 »

Если connect связывает 2 QObject созданных а разных нитках - то обмен сигнал/слот будет производиться только через QEvenLoop - и для DirectConnection тоже (просто вызывающий будет ждать пока событие принято из QEvenLoop приемника и обработано)
Здесь я был неправ (ошибся разбирая исходники). После критики BRE сделал тестовый примерчик (attachment) - да, все работает согласно документации, и вызов слота c DirectConnection происходит в нитке вызывающего.
Записан
brucemax
Гость
« Ответ #14 : Март 20, 2013, 10:15 »

Парни..  а если я из другого потока, который принимает данные из сети,  сигналом  передаю их (константной ссылкой QByteArrayем) в главный поток, ничего плохого случиться не может?=)    То есть в сетевом потоке постоянно создаются объекты(не динамически), одно из полей которых (именно этот QByteArray) эмититься в главный поток..  Так вот правильна ли моя логика, если я буду передавать этот bytearray константной ссылкой, то может получиться нехорошо, так как этот объект убьётся в сетевом потоке (ибо так он создавался не динамически в блоке), а мой главный поток будет юзать ссылку на него в это время  Непонимающий
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.087 секунд. Запросов: 23.