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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Стандартные грабли: QThread + connect = sendEvent assert  (Прочитано 6167 раз)
once_again_abc
Гость
« : Ноябрь 07, 2011, 10:18 »

Создаю стандартный тулбар с одной стороны, некоторый поток занимающийся своим делом с другой стороны. В потоке периодически сигналю. На этот сигнал подписываю слот тулбара. Слот вызывается (с некоторой задержкой) при использовании Qt::AutoConnection (по умолчанию) и отрабатывается нормально (m_pButton->setEnabled( true )Подмигивающий. Если же поменять флаг на Qt::DirectConnection, то получаю ассерт ниже:

Код:
void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver)
{
    QThread *currentThread = QThread::currentThread();
    QThread *thr = receiver->thread();
    Q_ASSERT_X(currentThread == thr || !thr,
               "QCoreApplication::sendEvent",
               QString::fromLatin1("Cannot send events to objects owned by a different thread. "
                                   "Current thread %1. Receiver '%2' (of type '%3') was created in thread %4")
               .arg(QString::number((quintptr) currentThread, 16))
               .arg(receiver->objectName())
               .arg(QLatin1String(receiver->metaObject()->className()))
               .arg(QString::number((quintptr) thr, 16))
               .toLocal8Bit().data());
    Q_UNUSED(currentThread);
    Q_UNUSED(thr);
}


как это лечить и куда смотреть?
Спасибо!
Записан
asvil
Гость
« Ответ #1 : Ноябрь 07, 2011, 10:22 »

Смотреть межпотоковые коммуникации.
Вы не можете использовать прямое подключение сигнал/слот между потоками.
Записан
once_again_abc
Гость
« Ответ #2 : Ноябрь 07, 2011, 11:03 »

Смотреть межпотоковые коммуникации.
Вы не можете использовать прямое подключение сигнал/слот между потоками.


а что взамен? какие варианты? ОС-специфик события?
Записан
asvil
Гость
« Ответ #3 : Ноябрь 07, 2011, 11:09 »

Аппаратные прерывания:)
А что вам вообще лечить то надо? Чем autoconnection не устроил?
Записан
once_again_abc
Гость
« Ответ #4 : Ноябрь 07, 2011, 11:35 »

Аппаратные прерывания:)
А что вам вообще лечить то надо? Чем autoconnection не устроил?

вот этим "(default) If the signal is emitted from a different thread than the receiving object, the signal is queued, behaving as Qt::QueuedConnection. Otherwise, the slot is invoked directly, behaving as Qt::DirectConnection. The type of connection is determined when the signal is emitted."

если между потоками нельзя использовать одну из главных фишек Qt то это просто смешно.
Записан
asvil
Гость
« Ответ #5 : Ноябрь 07, 2011, 12:11 »

Даже не знаю, что вам сказать. Перечитайте абзац еще раз или сформулируйте, что для вас является главным преимуществом использования Qt.
Записан
once_again_abc
Гость
« Ответ #6 : Ноябрь 07, 2011, 12:29 »

Даже не знаю, что вам сказать. Перечитайте абзац еще раз или сформулируйте, что для вас является главным преимуществом использования Qt.
[/quote

я чесно говоря тоже не знаю что вам сказать и даже не могу вам посоветовать перечитать что-либо, извините.
что касается основной причины, по которой я использую кьют - кроссплатформенность, удобная (хоть и не всегда) обертка над Вин32/ПОСИКС. когда то я делал подобное в меньших масштабах, здесь же предлагают постоянную поддержку и развитие, а так же для быстрого решения задач очень хороший вариант.
Записан
Странник
Гость
« Ответ #7 : Ноябрь 07, 2011, 12:34 »

зачем вам прямое соединение из вашего потока в gui? если вы хотите исполнять gui-слот в своем потоке, вы не правы. прочтите документацию.
Записан
once_again_abc
Гость
« Ответ #8 : Ноябрь 07, 2011, 13:25 »

зачем вам прямое соединение из вашего потока в gui? если вы хотите исполнять gui-слот в своем потоке, вы не правы. прочтите документацию.

в чем я не прав?
Записан
asvil
Гость
« Ответ #9 : Ноябрь 07, 2011, 14:13 »

вы неправы в том, что у вас одновременно будут выполнятся два метода класса, которые при этом потеницально могут использовать один и тот же участок памяти.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Ноябрь 07, 2011, 16:31 »

Создаю стандартный тулбар с одной стороны, некоторый поток занимающийся своим делом с другой стороны. В потоке периодически сигналю. На этот сигнал подписываю слот тулбара. Слот вызывается (с некоторой задержкой) при использовании Qt::AutoConnection (по умолчанию) и отрабатывается нормально (m_pButton->setEnabled( true )Подмигивающий. Если же поменять флаг на Qt::DirectConnection, то получаю ассерт ниже:
Если это "слот тулбара" - значит UI, а оно должно выполняться только в главной нитке. Поэтому здесь DirectConnection нельзя. Напр/вероятно Ваш слот вызвал event (для какого-то виджета) напрямую (nofify) и выполняется в нитке вызывающего. Но в это время главная нитка также делает notify - ну и crash.


Записан
Странник
Гость
« Ответ #11 : Ноябрь 07, 2011, 18:39 »

в чем я не прав?
собственно, полный перечень был приведен по ссылке. в двух словах, потокобезопасными операциями в системе сигнал-слот по версии Qt является отправка сигнала и вызов слота через очередь (ибо в этом случае слот выполняется в потоке принимающего, а не высылающего сигнал объекта). прямое соединение не является потокобезопасным, поскольку подразумевает выполнение слота в потоке высылающего сигнал объекта. следовательно, необходимо обеспечить синхронизацию потоков (как минимум, разделить доступ к общим данным). в классах-потомках QObject это не предусмотрено. итоги смотрите выше.
Записан
once_again_abc
Гость
« Ответ #12 : Ноябрь 07, 2011, 23:56 »

спасибо всем за помощь!   Целующий  Смеющийся
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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