Qt创建一个等待网络事件的对话框

时间:2016-02-05 15:37:09

标签: c++ multithreading qt

我正在为客户端/服务器应用程序编写客户端。客户端应该使用登录窗口登录。如果登录成功,则等待"窗口出现(这只是一个包含标签的窗口)。在服务器端,有一个等待n个客户端登录的屏障;当发生这种情况时,会播放一条消息,等待窗口应该关闭,并为每个客户端显示一个新窗口。

网络接口由我实现,使用低级功能,而不是Qt提供的功能。

实际的等待循环是这样的:

char buffer[256];
while (strcmp(buffer, "proceed"))
    read(sockfd, buffer, 256);

问题在于,如果我在主线程中启动此循环,则应用程序会阻塞,原因很明显。

如何运行此循环而不阻止应用程序,并在对话结束时关闭对话框?

稍后编辑:我也尝试使用QThreads,但是,由于我还不完全理解的原因,该应用程序仍然崩溃:

class WaitLoop : public QThread {
public:
    WaitLoop(NetworkHandler &network) : network(network) {}
private :
    NetworkHandler &network;
    void run() {
        this->network.waitForGameStart();
    }
};

在等待对话框构造函数中:

WaitLoop *waitLoop = new WaitLoop(network);
connect(waitLoop, SIGNAL(finished()), this, SLOT(gameStartSlot()));
waitLoop->start();

应用程序仍然使用此方法崩溃。

1 个答案:

答案 0 :(得分:0)

解决这个问题的最方法是不使用低级函数,因为你不是用C语言编写的。至少使用QAbstractSocket来包装sockfdsetSocketDescriptor方法允许您这样做。

然后您的代码变为非阻塞和异步:

class Controller : public QObject {
  Q_OBJECT
  QStateMachine m_sm;
  QState s_init{&m_sm}, s_proceeding{&m_sm};
  QAbstractSocket m_socket;
  Q_SIGNAL void proceed();
  Q_SLOT void onData() {
    auto data = m_socket.readAll();
    if (data.contains("proceed")) proceed();
  }
public:
  Controller(QObject * parent = 0) : QObject(parent) {
    connect(&m_socket, &QIODevice::readyRead, this, &Controller::onData);
    s_init.addTransition(this, &Controller::proceed, &s_proceeding);
    m_sm.setInitialState(&s_init);
    m_sm.start();
  }
  bool setup(quintptr fd) {
    return m_socket.setSocketDescriptor(fd);
  }
};

通过使用状态机,可以轻松添加更多状态,对其转换做出反应(请参阅QState::onEntry信号等),并确保行为正确。充实UML状态图迫使您考虑处理角落案例等。有关完整示例,请参阅this answer