crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

3 страниц V  < 1 2 3 >  
Ответить в данную темуНачать новую тему
> В каком контексте будет вызван слот, Работа с потоками
SABROG
  опции профиля:
сообщение 11.6.2009, 17:08
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Цитата(Litkevich Yuriy @ 11.6.2009, 17:52) *
вроде вот эта


Прикол в том, что я сам себе ответил. Однако проблема остается, если эмитить сигнал из главного потока в дочерний, то слот на этот сигнал выполнится в главном потоке. Это ведь не есть правильно, блокировать основной поток. Интересно как это можно обойти используя стандартные средства сигналов/слотов и цикла событий.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 11.6.2009, 17:11
Сообщение #12


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Я с потоками работал толькот одним способом:
Переопределяю в наследнике метод run(), из главного вызваю start().
Шлю в поток сигнал, управление сразу возвращается в главный поток.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 11.6.2009, 17:19
Сообщение #13


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Попытался воссоздать ситуацию:

#include <QtCore/QtGlobal>
#include <QtCore/QtDebug>
#include <QtCore/QCoreApplication>
#include <QtCore/QThread>

class Object : public QObject
{
    Q_OBJECT
public:
    Object(QObject *parent = 0) : QObject(parent) {}
    virtual ~Object() {}
public slots:
    void objectSlot()
    {
        qDebug() << "message from thread. Cur thread:" << thread()->currentThreadId();
    }
signals:
    void objectSignal();
protected:
    void timerEvent(QTimerEvent *event)
    {
        qDebug() << thread()->currentThreadId();
        emit objectSignal();
    }
};

class Thread : public QThread
{
    Q_OBJECT
public:
    Thread(QObject *parent = 0) : QThread(parent) {}
    void run()
    {
        parent()->connect(this, SIGNAL(threadSignal()), SLOT(objectSlot()));
        qDebug() << "try emit from thread: " << currentThreadId();
        emit threadSignal();
        exec();
    }
signals:
    void threadSignal();
        
public slots:
    void threadSlot()
    {
        qDebug() << "thread: " << currentThreadId();
        //quit();
    };
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Object object;
    Thread thread(&object);
    thread.connect(&object, SIGNAL(objectSignal()), SLOT(threadSlot()), Qt::QueuedConnection);
    thread.start();
    object.startTimer(1000);
    return a.exec();
}

#include "main.moc"


Хотел сделать что-то общения между потоками посредством сигналов. Главный поток пытается раз в секунду послать сигнал в дочерний поток, но слот вызывается в том же главном потоке несмотря на насильную установку флага Qt::QueuedConnection. Т.е. как ни крути, а все слоты вызываются из гуишного потока. А я хотел, чтобы цикл событий дочернего потока принял эвент о сигнале в run() и выполнил слот в своем потоке.

Сообщение отредактировал SABROG - 11.6.2009, 17:39
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 11.6.2009, 17:27
Сообщение #14


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(SABROG @ 11.6.2009, 21:19) *
Т.е. как ни крути, а все слоты вызываются из гуишного потока.
как ты такой вывод сделал?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 11.6.2009, 17:33
Сообщение #15


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(SABROG @ 11.6.2009, 18:08) *
Однако проблема остается, если эмитить сигнал из главного потока в дочерний, то слот на этот сигнал выполнится в главном потоке. Это ведь не есть правильно, блокировать основной поток. Интересно как это можно обойти используя стандартные средства сигналов/слотов и цикла событий.

Исходные данные: в главном потоке создается дочерний поток. Тут нужно сразу понять, что объект (!) дочернего потока (QThread и его наследники) создается в главном потоке и находится в контексте главного потока. Контекст дочернего потока образуется только после запуска потока (QThread::start). Контекст дочернего потока состоит из метода run(), все объекты созданные в нем, будут располагаться в контексте дочернего потока.
Теперь вспомним как Qt работает с межпоточными сигналами: при вызове сигнала, слот-обработчик которого находиться в другом контексте, Qt поместит специальное событие в очередь потока получателя и при очередном кванте времени из метода exec будет вызван нужный слот. Т.к. exec крутиться в контексте дочерней нити этот слот будет вызван в его контексте.

Почему же происходит что слот нити выполняется в главном? Для Qt объект дочерний нити находиться в контексте главной нити, поэтому сигнал-слот связывается на прямую и соответствено вызывается в контексте главной нити.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 11.6.2009, 17:36
Сообщение #16


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Цитата(Litkevich Yuriy @ 11.6.2009, 18:27) *
Цитата(SABROG @ 11.6.2009, 21:19) *
Т.е. как ни крути, а все слоты вызываются из гуишного потока.
как ты такой вывод сделал?


Я решил поэкспериментировать и пришел к такому вот странному решению:

thread.moveToThread(&thread);


Я назвал этот метод методом "Мюнхаузена" :lol:

Теперь действительно сигналы отправляются из главного потока и слот вызывается в дочернем потоке.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 11.6.2009, 17:41
Сообщение #17


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(SABROG @ 11.6.2009, 18:36) *
Я решил поэкспериментировать и пришел к такому вот странному решению:

thread.moveToThread(&thread);


Я назвал этот метод методом "Мюнхаузена" :lol:

Теперь действительно сигналы отправляются из главного потока и слот вызывается в дочернем потоке.

Этот метод был разработан несколькими днями ранее kuzulis. ;)
http://www.prog.org.ru/topic_9694_0.html
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 11.6.2009, 17:46
Сообщение #18


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(SABROG @ 11.6.2009, 21:36) *
Я назвал этот метод методом "Мюнхаузена"
Цитата(BRE @ 11.6.2009, 21:41) *
Этот метод был разработан несколькими днями ранее kuzulis.
на что Константин сказал:
Цитата
улыбнуло...ассоциируется с картинкой, где чел сам себе в зад залазит
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 11.6.2009, 17:56
Сообщение #19


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Цитата(BRE @ 11.6.2009, 18:41) *
Этот метод был разработан несколькими днями ранее kuzulis.


Если верить его словам, то даже не им, он где-то это увидел :)

Жаль авторство не могу себе присвоить ^_^ , хотя конечно решение самом себе в голову напрашивается.

Улыбнула фраза Константина

Цитата
собсна, вообще не удивительно.
а вот tc->moveToThread(tc) улыбнуло...ассоциируется с картинкой, где чел сам себе в зад залазит /* может видел кто? */ Улыбающийся


Ну хотябы могу себе название метода "Мюнхгаузена" присвоить ;)

---
Кстати, скорее всего человек увидел этот метод отсюда http://forum.vingrad.ru/forum/topic-241300...y1737536/0.html Этот топик один из первых выдается в гугле на поиск moveToThread.

Еще немного погуглил и нашел такую переписку с канала #Qt:

Цитата
[04:58] <daniel> thiago_home: Yeah I just noticed I don't have to wait.
[04:59] <daniel> Is "thread.start(); thread.moveToThread(&thread);" ok?
[05:00] <thiago_home> yes


Собственно, я так понимаю, что thiago_home это Thiago Macieira, раз он одобряет этот метод, то почему бы троллям не предложить ввести что-то типа флага, чтобы объект сразу сам в себя перемещался внутри метода start().

wasyota тоже такой метод предлагает.
---
Может поместить это решение в "Секреты и интересные возможности" ?

Сообщение отредактировал SABROG - 11.6.2009, 18:53
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 11.6.2009, 20:06
Сообщение #20


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Цитата(Litkevich Yuriy @ 11.6.2009, 18:46) *
Жаль авторство не могу себе присвоить , хотя конечно решение самом себе в голову напрашивается.
Себе авторство тоже присвоить не могу, но если посмотришь здесь (в атаче), увидишь, что я пришел к такому же решению. Я тогда только разбирался в этом вопросе, и сделал так скорее по незнанию. Я предлогаю делать так
ThreadSocket::ThreadSocket(QObject *parent)
    : QThread(parent)
{
    moveToThread(this);
}
На мой взгляд, это будет правильнее.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

3 страниц V  < 1 2 3 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


7 чел. читают эту тему (гостей: 7, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 25.11.2024, 22:54