Russian Qt Forum

Qt => Вопросы новичков => Тема начата: once_again_abc от Ноябрь 07, 2011, 10:18



Название: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: 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);
}


как это лечить и куда смотреть?
Спасибо!


Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: asvil от Ноябрь 07, 2011, 10:22
Смотреть межпотоковые коммуникации.
Вы не можете использовать прямое подключение сигнал/слот между потоками.


Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: once_again_abc от Ноябрь 07, 2011, 11:03
Смотреть межпотоковые коммуникации.
Вы не можете использовать прямое подключение сигнал/слот между потоками.


а что взамен? какие варианты? ОС-специфик события?


Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: asvil от Ноябрь 07, 2011, 11:09
Аппаратные прерывания:)
А что вам вообще лечить то надо? Чем autoconnection не устроил?


Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: once_again_abc от Ноябрь 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 то это просто смешно.


Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: asvil от Ноябрь 07, 2011, 12:11
Даже не знаю, что вам сказать. Перечитайте абзац еще раз или сформулируйте, что для вас является главным преимуществом использования Qt.


Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: once_again_abc от Ноябрь 07, 2011, 12:29
Даже не знаю, что вам сказать. Перечитайте абзац еще раз или сформулируйте, что для вас является главным преимуществом использования Qt.
[/quote

я чесно говоря тоже не знаю что вам сказать и даже не могу вам посоветовать перечитать что-либо, извините.
что касается основной причины, по которой я использую кьют - кроссплатформенность, удобная (хоть и не всегда) обертка над Вин32/ПОСИКС. когда то я делал подобное в меньших масштабах, здесь же предлагают постоянную поддержку и развитие, а так же для быстрого решения задач очень хороший вариант.


Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: Странник от Ноябрь 07, 2011, 12:34
зачем вам прямое соединение из вашего потока в gui? если вы хотите исполнять gui-слот в своем потоке, вы не правы. прочтите документацию (http://doc.qt.nokia.com/latest/threads-qobject.html).


Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: once_again_abc от Ноябрь 07, 2011, 13:25
зачем вам прямое соединение из вашего потока в gui? если вы хотите исполнять gui-слот в своем потоке, вы не правы. прочтите документацию (http://doc.qt.nokia.com/latest/threads-qobject.html).

в чем я не прав?


Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: asvil от Ноябрь 07, 2011, 14:13
вы неправы в том, что у вас одновременно будут выполнятся два метода класса, которые при этом потеницально могут использовать один и тот же участок памяти.


Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: Igors от Ноябрь 07, 2011, 16:31
Создаю стандартный тулбар с одной стороны, некоторый поток занимающийся своим делом с другой стороны. В потоке периодически сигналю. На этот сигнал подписываю слот тулбара. Слот вызывается (с некоторой задержкой) при использовании Qt::AutoConnection (по умолчанию) и отрабатывается нормально (m_pButton->setEnabled( true );). Если же поменять флаг на Qt::DirectConnection, то получаю ассерт ниже:
Если это "слот тулбара" - значит UI, а оно должно выполняться только в главной нитке. Поэтому здесь DirectConnection нельзя. Напр/вероятно Ваш слот вызвал event (для какого-то виджета) напрямую (nofify) и выполняется в нитке вызывающего. Но в это время главная нитка также делает notify - ну и crash.




Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: Странник от Ноябрь 07, 2011, 18:39
в чем я не прав?
собственно, полный перечень был приведен по ссылке. в двух словах, потокобезопасными операциями в системе сигнал-слот по версии Qt является отправка сигнала и вызов слота через очередь (ибо в этом случае слот выполняется в потоке принимающего, а не высылающего сигнал объекта). прямое соединение не является потокобезопасным, поскольку подразумевает выполнение слота в потоке высылающего сигнал объекта. следовательно, необходимо обеспечить синхронизацию потоков (как минимум, разделить доступ к общим данным). в классах-потомках QObject это не предусмотрено. итоги смотрите выше.


Название: Re: Стандартные грабли: QThread + connect = sendEvent assert
Отправлено: once_again_abc от Ноябрь 07, 2011, 23:56
спасибо всем за помощь!   :-*  ;D