2013-10-15 5 views
4

У меня есть 3 QThreads, вызывающих друг друга (все унаследованы от QThread. Я знаю, что некоторые могут предлагать использовать moveToThread, но просто игнорировать этот факт пока). Упрощенный код выглядит следующим образом:Невозможно подключиться между QThread с завершенным() сигналом для нескольких Qthread

thread1 класс:

void 
Thread1::run 
{ 
    // some execution 
    Thread2 t2 = new Thread2(); 
    connect(t2,SIGNAL(finished),this,SLOT(onFinished)); 
    t2->start(); 

    while(!stop) // stop was initialized as false 
    { 
     this->msleep(10); 
    }  
} 
void Thread1::onFinished(){ stop = true; } 

thread2 класс:

void 
Thread2::run 
{ 
    // some execution 
    Thread3 t3 = new Thread3(); 
    connect(t3,SIGNAL(finished),this,SLOT(onFinished)); 
    t3->start(); 

    while(!stop) // stop was initialized as false 
    { 
     this->msleep(10); 
    }  
} 
void Thread2::onFinished(){ stop = true; } 

Thread3 класс:

void 
Thread3::run 
{ 
    // some execution 
    QMutexLocker ml(&mMutex); 
} 

Когда у меня есть только две темы, это работает отлично (например, только thread2 и thread3). Метод onFinished() кажется, что соединение с готовым() сигналом больше не подходит, после того как я перешел к сценарию с тремя потоками. OnFinished() в thread2 когда-либо был вызван. И я уверен, что выполнение потока3 завершено.

Может ли кто-нибудь сказать мне, где я мог бы сделать неправильно?

+0

Я не вижу ошибок в части кода, который вы опубликовали. Попробуйте использовать 'qDebug()', чтобы узнать, возвращает ли 'connect' true и если на самом деле вызывается' onFinished() 'слоты. –

+0

@TimMeyer, у меня была распечатка на onFinished(), но ничего не было распечатано. В основном программа застревает в цикле while в thread2. Но я уверен, что thread3 закончил, потому что у меня также есть отладочная распечатка в конце метода run(). –

ответ

6

Прежде всего, вы должны отметить, что тип подключения по умолчанию - Qt::AutoConnection. Это означает, что если сигнал испускается из другого потока, кроме потока принимающего объекта, используется Qt::QueuedConnection. В этом случае: 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. Итак, вам нужен цикл событий.

Он работает с 2 потоками, потому что у вас, вероятно, есть цикл событий, запущенный в вашей основной теме. В вашем случае, когда вы используете только thread2 и thread3 объектов, thread2 объект фактически будет жить в основной теме, а объект thread3 будет жить в потоке, управляемом объектом thread2. Таким образом, слоты в объекте thread2 должны работать.

Но в случае 3 витка резьбы, thread1 объекта будет жить в главном потоке, thread2 объекта будет жить в потоке под управлением thread1 объекта, и потому нет запуска цикла событий там, слота thread2 объекта никогда не будет быть казненным.

Вы можете позвонить QThread::exec() в свою QThread::run() функцию, но обратите внимание, что слоты будут исполняться в потоке, в котором находится ваш объект QThread, а не тот поток, которым он управляет. Из-за этого вы не должны использовать слоты в подклассах QThread. Вы должны создать подкласс QObject и перенести его в поток.

Другим вариантом является использование Qt::DirectConnection для подключения, когда вы подключаете свои сигналы к слотам.

+0

Спасибо за объяснение! Qt :: DirectConnection, похоже, решает проблему. Когда вы говорите «создайте подкласс QObject и переместите его в поток», ссылаетесь ли вы на метод moveToThread? Я могу попробовать этот метод, так как я изменяю некоторые переменные в методе onFinished(), поэтому я боюсь, что Qt :: DirectConnection может быть проблемой? –

+0

@JohnYang Да, я. В случае 'Qt :: DirectConnection' он работает как прямой вызов функции. – thuga

Смежные вопросы