2013-08-13 3 views
2

У меня возникли проблемы с QTcpSocket, это не испуская никаких сигналов:/Почему QTcpSocket не излучает сигналы?


void NetworkInstance::run() 
{ 
    m_pSocket = new QTcpSocket(); 
    connect(m_pSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError())); 
    connect(m_pSocket, SIGNAL(hostFound()), this, SLOT(socketHostLookupDone())); 
    connect(m_pSocket, SIGNAL(connected()), this, SLOT(socketConnected())); 
    connect(m_pSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); 

    connect(m_pSocket, SIGNAL(readyRead()), this, SLOT(socketReadyRead())); 

    QSettings s; 
    s.beginGroup("network"); 
    emit log(QString("Connection to: ").append(s.value("host").toString()).append(":").append(s.value("port").toString())); 
    m_pSocket->connectToHost(s.value("host").toString(), s.value("port").toInt()); 
    s.endGroup(); 

    exec(); 
} 

Это мой код, я не вижу в ней ошибку, но не подключенный сигнал излучающая (hostFound, подключено , и т.д.). На сервере я вижу, что соединение установлено и отправлено данные, но ничего не происходит на стороне клиента. NetworkInstance расширяет QThread.

+2

Если вы подклассов QThread, «вы делаете это неправильно»: http://blog.qt.digia.com/blog/2010/06/ 17/youre-doing-it-wrong/ – TheDarkKnight

+0

Вам вообще не нужен QThread! Вы можете безопасно запустить это в основном потоке, после чего QTcpSocket работает асинхронно. –

+0

Мне нужен QThread, я делаю некоторую тяжелую обработку с полученными данными (и да, можно было бы поместить обработку в QThread самостоятельно, но это проще). У меня есть один сокет на поток, он соответствует моим потребностям. Однако принятый ответ - это решение. – Paladin

ответ

2

На основании моего более раннего комментария о том, что подклассификация QThread неверна, вам нужно создать свой класс, унаследованный от QObject, а затем переместить его в новый QThread.

Так ты есть класс, который выглядит примерно так: -

class NetworkInstance : public QObject 
{ 
    Q_OBJECT 

public: 
    NetworkInstance(); 

public slots: 
    void Run(); 

    void socketConnected(); 
    void socketError(); 
    // etc for other slots... 

private: 
    class QTCPSocket* m_pSocket; 
} 

Создайте свой сетевой объект экземпляра и нитку: -

QThread* pThread = new QThread; 
NetworkInstance* pNetworkInstance = new NetworkInstance; 

Создать экземпляр QTcpSocket и подключить сигналы/слоты в вашем классе NetworkInstance, а затем создайте QThread и переместите свой класс в поток: -

pNetworkInstance->moveToThread(pThread); 

Наконец, начать бег резьбы: -

pThread->start(); 
+0

Менее сложным способом достижения той же цели является подкласс QObject AND QRunnable, а затем передать работника QThreadPool – RobbieE

+0

Не совсем «менее сложный» IMHO, но я согласен, что это еще один возможный метод. – TheDarkKnight

+0

на самом деле ему вообще не нужен QThread. QTCPSocket работает асинхронно. –

0

Я уверен, что сигналы излучаются. Я не уверен, что они получены слотами в другом потоке. Должно быть. Как обычно.

Qt :: AutoConnection

(по умолчанию) Если сигнал испускается из другого потока, чем принимающего объекта, сигнал ставится в очередь, ведет себя, как Qt :: QueuedConnection. В противном случае слот вызывается напрямую, ведет себя как Qt :: DirectConnection. Тип соединения определяется при испускании сигнала.

Но теперь вы запускаете свой собственный eventloop с помощью exec() в run().

Edit: Ааа ... Я вижу ...

Qt :: QueuedConnection

слот вызывается, когда управление возвращается в цикл событий нити приемника. Слот выполнен в потоке приемника .

Это то, что автоматически используется, поскольку отправитель и получатель находятся в разных потоках. Но с вашим «exec()» элемент управления никогда не возвращается к потоку получателя.

+0

так .. лет сказать, я не должен начинать собственный eventloop с exec()? Я не уверен, как это будет работать без него, но пробовал и не помогал. – Paladin

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