Qt 槽调用两次

Qt slot invokes twice

mainwindow 中有一个插槽 MainWindow::establish_connection,我试图在其中调用不同线程中的 Server::establish_connection

void MainWindow::establish_connection(const std::string& nickname,
                                      const std::string& ip, int port)
{ 
    auto thread = new QThread(this);
    remote_server = new Server(nickname, ip, port);

    connect(thread, SIGNAL(started()), remote_server, SLOT(establish_connection()));

    connect(remote_server, SIGNAL(connected()), this, SLOT(connection_established()));

    connect(remote_server, SIGNAL(readyRead()), this, SLOT(handle_reply()));

    connect(remote_server, SIGNAL(error(QAbstractSocket::SocketError)), this,
            SLOT(connection_failed(QAbstractSocket::SocketError)));

    connect(remote_server, SIGNAL(stop_thread()), thread, SLOT(quit()));

    thread->start();
}

Server::establish_connection方法:

void Server::establish_connection()
{
    master_socket = std::move(
                std::unique_ptr<QTcpSocket>(new QTcpSocket(nullptr)));

    connect(master_socket.get(), SIGNAL(connected()), SIGNAL(connected()));

    connect(master_socket.get(), SIGNAL(readyRead()), SIGNAL(readyRead()));
    connect(master_socket.get(), SIGNAL(error(QAbstractSocket::SocketError)),
            SIGNAL(error(QAbstractSocket::SocketError)));

    master_socket->connectToHost(ip.c_str(), port);
    if (!master_socket->waitForConnected(timeout*1000))
    {
        emit error(master_socket->error());

    }
    emit stop_thread();
}

但是当 error 信号发出时,MainWindow::connection_failed 调用两次。

void MainWindow::connection_failed(QAbstractSocket::SocketError e)
{
    QString err_msg = remote_server->get_socket()->errorString();

    qDebug() << err_msg;
}

输出:

"Connection refused"
"Connection refused"

如何防止这个问题?

这里你重新发出来自 master_socket 的信号错误:connect(master_socket.get(), SIGNAL(error(QAbstractSocket::SocketError)), SIGNAL(error(QAbstractSocket::SocketError)));

这对我来说似乎是第一。

这里你在超时后自己发出:

if (!master_socket->waitForConnected(timeout*1000))
{
    emit error(master_socket->error());

}

这似乎是你的第二名。

我认为当您等待超时 error() 时,它已经被您的 connect() 发出并转发。之后你又自己发射它。这个好像超级流畅

测试删除此显式发出是否对您有用。

或者,您可以将行 connect(master_socket.get(), SIGNAL(error(QAbstractSocket::SocketError)), SIGNAL(error(QAbstractSocket::SocketError))); 放在 if 条件之后,以获取从该点开始的所有错误。无需断开连接。

或者将其放在 else 分支中,因为您只对可以建立连接的任何更多错误感兴趣:

if (!master_socket->waitForConnected(timeout*1000))
{
    emit error(master_socket->error());

} else {

   connect(master_socket.get(), SIGNAL(error(QAbstractSocket::SocketError)),
        SIGNAL(error(QAbstractSocket::SocketError)));
}

两者都应该有效。