Qt插槽调用两次

时间:2015-12-09 16:15:24

标签: c++ multithreading qt sockets signals-slots

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"

如何防止此问题?

1 个答案:

答案 0 :(得分:1)

这里你重新发出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)));
}

两者都应该有用。