如何安全地停止std线程?

Bom*_*uin 12 c++ multithreading join boost-asio

我正在开发一个聊天服务器,我有一个问题.

如何std::thread安全停车?

像这样很容易出问题.

thread t(&func);
t.join();
Run Code Online (Sandbox Code Playgroud)

但是,如果func具有无限循环,则连接不起作用.

这是我的来源.

void CServerSocket::AcceptRun(boost::asio::io_service &iosrv)
{
    while (true)
    {
        auto sock = std::make_shared<boost::asio::ip::tcp::socket>(iosrv);
        m_Acceptor->accept(*sock);

        m_SocketList.push_back(std::make_shared<CConnectionSocket>(this, sock));
    }
}
Run Code Online (Sandbox Code Playgroud)

CServerSocket::~CServerSocket()
{
    CLogManager::WriteLog("Stopping Server...");
    m_Acceptor->close();
    m_Acceptor.reset();

    // m_AcceptThread.detach(); This is right?

    CLogManager::WriteLog("Server Stoped!");
}
Run Code Online (Sandbox Code Playgroud)

我很纳闷.请帮我.谢谢.

Die*_*ühl 9

您可以将合适的上下文传递给您的线程,该线程可以包含一个标志,指示是否该停止.国旗可能是一个std::atomic<bool>.显然,你还需要设置通信,不要无限期地等待数据,这样你就有机会偶尔检查一下标志.


Mik*_*our 3

我相当确定,accept当您关闭接受器时,它将干净地退出,并抛出异常。您应该捕获异常以便线程正常退出:

void CServerSocket::AcceptRun(boost::asio::io_service &iosrv)
try {
    // your loop here, unchanged
} catch (std::exception const & ex) {
    // perhaps log the message, ex.what()
}
Run Code Online (Sandbox Code Playgroud)

然后在关闭接受器之后但在销毁它之前加入线程:

CServerSocket::~CServerSocket()
{
    CLogManager::WriteLog("Stopping Server...");
    m_Acceptor->close();
    m_AcceptThread.join();
    CLogManager::WriteLog("Server Stopped!");

    // No need to do anything else with m_Acceptor, assuming it's a smart pointer
}
Run Code Online (Sandbox Code Playgroud)

就个人而言,我会使用异步操作,除非有令人信服的理由使用多线程。单线程更容易处理。