【问题标题】:How to stop a thread containing a while(1)如何停止包含 while(1) 的线程
【发布时间】:2014-06-26 14:00:38
【问题描述】:

我在我的班级MainWindow 中创建了一个启动server 的线程,当我关闭这个MainWindow 时,我需要停止该服务器,但我不能因为该服务器在while(true) loop 中运行。所以我看到的唯一可能就是杀死包含服务器的线程。

但这仍然不可能,因为我使用了#include <thread>C++11

我的解决方案是将boolean 传递给我的服务器,并执行循环,而这个布尔值是真的。但是当我的布尔值变为假时,我无法退出循环,因为我的服务器等待接收在完成循环之前没有出现的帧。

这是我的代码:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //Some initialisation
...

    // Constructs the new thread and runs it. Does not block execution.
    m_t1 = std::thread(lancerServeur);

}

MainWindow::~MainWindow()
{
    delete ui;
    m_t1.join();
}


void MainWindow::lancerServeur(){
    serveur s;
    while(true){
        s.receiveDataUDP();//Wait for a frame
    }
}

那么,有没有办法在 C++11 中杀死我的线程,或者你有没有办法停止我的服务器?

谢谢。

【问题讨论】:

  • 你不能,不是以安全或便携的方式。您可以让循环检查一些变量(可能是condition variable)并在设置时退出,而不是无限循环。
  • 不是标准方式,不是。 C++11 断言线程需要相互协作;所以主线程需要通知子线程退出。我记得在他们将其添加到规范中时读到了这一点,它与整个程序的稳定性有关。如果线程从外部终止,它可能会使事物处于不确定状态。
  • @JoachimPileborg 我不能因为我的服务器等待一帧,然后暂停我的线程。
  • 您需要修改s.receiveDataUDP();,使其不会阻塞或使用事件。
  • @JohnnyMopp 我要等一帧,不等怎么办。

标签: c++ multithreading qt c++11 network-programming


【解决方案1】:

如果它是一个 UDP 服务器,并且您想解除对它的阻止,以便它读取某个“停止”布尔值为真,请设置该布尔值并在本地堆栈上向其发送一条 UDP 消息,从而解除对它的阻止。

【讨论】:

    【解决方案2】:

    您需要有一个主线程将发出信号的事件。然后您的线程等待该事件和帧的接收。当等待返回时,您检查导致等待结束的条件。如果接收到帧,则处理该帧并再次等待。如果是线程结束事件,则退出线程。

    我不太了解新的标准线程库,还不能建议如何使用它们。使用 Windows 原生 API,您将使用 WaitForMultipleObjects()

    【讨论】:

      【解决方案3】:

      您可以创建一个指向线程对象的指针,然后在析构函数中删除该对象。

      换句话说:

          m_t1 = new std::thread(lancerServeur);
      

      然后在你的析构函数中:

          m_t1->detach();
          delete m_t1;
      

      当然还有将 memnber 变量改为指针:

          std::thread* m_t1;
      

      或您选择的任何其他指针。

      编辑:您还必须在析构函数中调用“m_t1->detach()”,以确保线程在销毁时不可加入。在您提供的代码示例中,情况并非如此。

      【讨论】:

      • 是的,你是对的。线程需要分离然后销毁。我最初误读了 std::terminate() 的功能。我已经编辑了我的答案。
      • 我认为 OP 的问题在于停止线程。在销毁std::thread 对象之前将其分离将使线程继续运行。
      • 在这种情况下,在堆上分配 std::thread 如何完成任何事情?
      • @ComicSansMS:可以随时删除对象/线程
      • 可以在需要时删除对象/线程 - 这根本没有解决最初的问题。
      猜你喜欢
      • 2019-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多