Почему слоты вызываются из основного потока? - PullRequest
1 голос
/ 02 октября 2010

У меня есть приложение Qt, которое имеет два потока: основной поток, который обрабатывает графический интерфейс, и второй поток, который управляет сетевыми подключениями. Вот код потока:

void thread::run()
{
    QTcpServer server;

    server.connect(&server,SIGNAL(newConnection()),this,SLOT(OnConnect()));

    //...
}

Когда я ставлю точку останова в начале OnConnect() и отлаживаю приложение, оно сообщает, что OnConnect() вызывается из основного потока!

Как мне запустить OnConnect() в том же потоке, что и QTcpServer?

Ответы [ 2 ]

4 голосов
/ 04 октября 2010

Чтобы дать более подробный ответ, посмотрите немного глубже, как взаимодействуют соединения сигнальных слотов и контексты потоков. По сути, для большего количества соединений (авто-соединение) слот будет вызываться напрямую, если и излучатель, и получатель находятся в одном и том же контексте потока, в противном случае это будет соединение в очереди, а слот будет запущен в контексте потока объект, который содержит слот. В этом случае он должен быть поставлен в очередь, что подразумевает, что ваш поток является частью контекста потока основного приложения, а не его собственным. Это подтверждается документацией Qt предоставляет обзор его потоков, где говорится, что экземпляр QThread "принадлежит" контексту потока, который его создал, а не контексту потока, который он представляет. Это означает, что у вас есть три основных варианта:

  1. Вы можете использовать moveToThread (), чтобы переместить поток в его собственный контекст. Обратите внимание, что это может вызвать проблемы при удалении потока, если вы не переместите его обратно в контекст, где он будет уничтожен, и это может быть сделано только в контексте исходного потока, так что это должно быть сделано до выхода из функции запуска.
  2. Вы можете рассматривать экземпляр QThread как дескриптор потока, а не как часть самого потока. Если вам нужно, чтобы что-то было сделано в контексте нового потока, создайте другой объект для обработки этого и создайте его экземпляр в контексте нового потока (внутри функции run). Это то, что я бы порекомендовал.
  3. Принудительное прямое соединение. Это означает, что вам нужно убедиться, что код, работающий в слоте, является поточно-ориентированным, игнорируя встроенные в Qt методы, которые делают эти функции поточно-ориентированными. Это то, что вы сделали .
0 голосов
/ 02 октября 2010

Кажется, проблема в том, что я не передавал Qt::DirectConnection как последний параметр connect().

После добавления это сработало.

...