Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过外部信号停止std::线程的有效方法是什么?_C++_Multithreading_C++11 - Fatal编程技术网

C++ 通过外部信号停止std::线程的有效方法是什么?

C++ 通过外部信号停止std::线程的有效方法是什么?,c++,multithreading,c++11,C++,Multithreading,C++11,这是一个不按设计工作的代码,请解释我这里的错误(代码简化,使其更具可读性) 通过使shm_服务器可复制,你不知何故把自己的脚撞到了地上。我相信您这样做是为了消除编译器错误,并不是因为该类上的复制语义特别有用。我建议您再次删除该构造函数。如果确实需要复制语义,请让构造函数通过引用const获取其参数 class shm_server // cannot copy or move { std::atomic_bool done_ {}; public: void operator

这是一个不按设计工作的代码,请解释我这里的错误(代码简化,使其更具可读性)


通过使
shm_服务器
可复制,你不知何故把自己的脚撞到了地上。我相信您这样做是为了消除编译器错误,并不是因为该类上的复制语义特别有用。我建议您再次删除该构造函数。如果确实需要复制语义,请让构造函数通过引用
const
获取其参数

class shm_server  // cannot copy or move
{

  std::atomic_bool done_ {};

public:

  void
  operator()()
  {
    this->run();
  }

  void
  run()
  {
    using namespace std::chrono_literals;
    while (!this->done_.load())
      {
        std::clog << std::this_thread::get_id() << " working..." << std::endl;
        std::this_thread::sleep_for(1ms);
      }
  }

  void
  stop()
  {
    this->done_.store(true);
  }

};
编译器不会让您这样做,因为它会尝试复制不可复制的
server
对象

必须将
服务器
对象包装到一个类似于引用的对象中

shm_server server {};
std::thread worker {std::ref(server)};
这会按预期工作,并有效地将指针传递到
std::thread
构造函数,而不是实际的
服务器
对象

然而,我发现这并不是最直接的解决方案。您真正想要做的是在不同的线程上运行
服务器的成员函数。而
std::thread
的构造函数允许您这样做

shm_server server {};
std::thread worker {&shm_server::run, &server};
这里,我将
run
成员函数的地址和指向
server
对象的指针(将作为隐式
this
指针传递)作为参数传递。我引入了
run
函数,因为语法可能不那么烦人。您也可以直接传递呼叫接线员的地址

shm_server server {};
std::thread worker {&shm_server::operator(), &server};
这是一个完整的例子

int
main()
{
  using namespace std::chrono_literals;
  std::clog << std::this_thread::get_id() << " starting up" << std::endl;
  shm_server server {};
  std::thread worker {&shm_server::operator(), &server};
  //std::thread worker {std::ref(server)};                 // same effect
  //std::thread worker {&shm_server::run, &server};        // same effect
  std::this_thread::sleep_for(10ms);
  server.stop();
  worker.join();
  std::clog << std::this_thread::get_id() << " good bye" << std::endl;
}
如果您认为一个
shm_服务器
只有在它自己的线程上运行时才有用,那么您还可以给它一个
std::thread
作为数据成员,并让它的构造函数(或者一个专用的
start
成员函数,如果您愿意)启动并让它的析构函数加入线程

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>

class shm_server
{

  std::atomic_bool done_ {};
  std::thread worker_ {};

public:

  shm_server()
  {
    this->worker_ = std::thread {&shm_server::run_, this};
  }

  ~shm_server()
  {
    this->done_.store(true);
    if (this->worker_.joinable())
      this->worker_.join();
  }

private:

  void
  run_()
  {
    using namespace std::chrono_literals;
    while (!this->done_.load())
      {
        std::clog << std::this_thread::get_id() << " working..." << std::endl;
        std::this_thread::sleep_for(1ms);
      }
  }

};


int
main()
{
  using namespace std::chrono_literals;
  std::clog << std::this_thread::get_id() << " starting up" << std::endl;
  {
    shm_server server {};
    std::this_thread::sleep_for(10ms);
  }
  std::clog << std::this_thread::get_id() << " good bye" << std::endl;
}
#包括
#包括
#包括
#包括
类shm_服务器
{
std::原子布尔完成{};
std::线程工作线程{};
公众:
shm_服务器()
{
this->worker=std::thread{&shm\u server::run\uu,this};
}
~shm_server()
{
此->完成存储(true);
如果(此->工作者可接合())
此->worker_u2;.join();
}
私人:
无效的
跑()
{
使用名称空间std::chrono_文本;
而(!this->done_uz.load())
{

std::clog Try
std::threads{std::ref(服务器)}
为避免复制相关:谢谢!std::ref解决方案可为我提供详细解释。是的,我添加了复制ctor,但没有真正分析内部问题,只是看到了复制原子库的问题。在使用std::ref的建议后,我已将其删除为未使用。关于成员传递。我使用了对象本身,而不是r由于某种原因,它看起来比函数传递更清晰,所以实际上,成员传递对于功能来说是可以的。关于服务器内部的线程对象的问题:这种模式更可取吗?有什么优点吗?将线程逻辑封装在服务器类中可以让客户端不必担心它。另一方面,它使设计不够灵活。可能有些客户希望在自己的线程上运行它,或者使用另一个线程库。还要考虑单元可测试性。我不知道什么能很好地适合您的用例。谢谢,封装对我来说更可取,客户希望“创建并忘记”关于服务器对象。理想情况下,服务器应该完全自己管理所有对象
shm_server server {};
std::thread worker {&shm_server::operator(), &server};
int
main()
{
  using namespace std::chrono_literals;
  std::clog << std::this_thread::get_id() << " starting up" << std::endl;
  shm_server server {};
  std::thread worker {&shm_server::operator(), &server};
  //std::thread worker {std::ref(server)};                 // same effect
  //std::thread worker {&shm_server::run, &server};        // same effect
  std::this_thread::sleep_for(10ms);
  server.stop();
  worker.join();
  std::clog << std::this_thread::get_id() << " good bye" << std::endl;
}
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>

class shm_server
{

  std::atomic_bool done_ {};
  std::thread worker_ {};

public:

  shm_server()
  {
    this->worker_ = std::thread {&shm_server::run_, this};
  }

  ~shm_server()
  {
    this->done_.store(true);
    if (this->worker_.joinable())
      this->worker_.join();
  }

private:

  void
  run_()
  {
    using namespace std::chrono_literals;
    while (!this->done_.load())
      {
        std::clog << std::this_thread::get_id() << " working..." << std::endl;
        std::this_thread::sleep_for(1ms);
      }
  }

};


int
main()
{
  using namespace std::chrono_literals;
  std::clog << std::this_thread::get_id() << " starting up" << std::endl;
  {
    shm_server server {};
    std::this_thread::sleep_for(10ms);
  }
  std::clog << std::this_thread::get_id() << " good bye" << std::endl;
}