为什么QTcpSocket没有发出信号?

4

我遇到了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、connected等等)。在服务器上,我可以看到连接已经建立并且数据已经发送,但是客户端什么也没有发生。NetworkInstance正在扩展QThread。


3
如果您正在子类化QThread,"您是错误的": http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/注:该文章表达了Qt开发团队在使用多线程时不建议直接继承QThread类的观点。 - TheDarkKnight
你根本不需要 QThread!你可以在主线程中安全地运行它,毕竟 QTcpSocket 是异步工作的。 - Marek R
1
我需要 QThread,在接收到数据后进行一些重型处理(是的,将处理放入 QThread 中本身是可能的,但这样更简单)。我每个线程有一个套接字,它适合我的需求。然而被接受的答案才是解决方案。 - graywolf
2个回答

3
基于我之前评论中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();

一个更简单的实现方式是继承QObject和QRunnable类,然后将worker传递给QThreadPool。 - RobbieE
不完全是,依我之见并不是“更简单”,但我同意这是另一种可能的方法。 - TheDarkKnight
事实上,他根本不需要QThread。 QTCPSocket可以异步工作。 - Marek R
是的,但也许他的类会处理传入的数据包,并希望在不同的线程上执行该操作。 - TheDarkKnight

0

我确信信号已经被发出。但我不确定它们是否被另一个线程中的槽函数接收到。理论上应该是这样的。

Qt::AutoConnection

(默认) 如果信号是从与接收对象不同的线程中发出的,则该信号将排队,表现为 Qt::QueuedConnection。否则,槽函数将直接调用,表现为 Qt::DirectConnection。连接类型在信号发出时确定。

但现在你在 run() 中启动了自己的事件循环。

编辑:啊...我明白了...

Qt::QueuedConnection

当控制权返回接收者线程的事件循环时,将调用槽函数。槽函数在接收者线程中执行。

这就是由于发送方和接收方位于不同的线程中,因此自动使用的方式。但是由于您的 'exec()',控制权永远不会返回到接收者的线程。


所以,你的意思是我不应该使用exec()来启动自己的事件循环?我不确定如果没有它会怎样运作,但我尝试了一下,没有帮助。 - graywolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接