チャットサーバーを開発していますが、質問があります。
停止する方法std::thread
安全ですか?
このように非常に簡単な問題です。
thread t(&func);
t.join();
ただし、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));
}
}
そして
CServerSocket::~CServerSocket()
{
CLogManager::WriteLog("Stopping Server...");
m_Acceptor->close();
m_Acceptor.reset();
// m_AcceptThread.detach(); This is right?
CLogManager::WriteLog("Server Stoped!");
}
とても不思議です。私を助けてください。ありがとうございました。
アクセプターを閉じると、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()
}
次に、アクセプターを閉じた後、それを破棄する前にスレッドに参加します。
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
}
個人的には、複数のスレッドを使用するやむを得ない理由がない限り、非同期操作を使用します。単一のスレッドははるかに扱いやすいです。
適切なコンテキストをスレッドに渡すことができます。このコンテキストには、停止する時間かどうかを示すフラグを含めることができます。フラグはstd::atomic<bool>
。もちろん、データを無期限に待たないように通信を設定する必要があるので、たまにフラグをチェックする機会があります。
Std :: threadを安全に停止する方法は?
スレッドを安全に停止するということは、スレッド関数に処理を停止するように指示し(std::thread
の外部にあるメカニズムを介して)、スレッドが停止するのを待つことを意味します。
@ DietmarKuhlからの応答 は、これを行う方法を示しています。アクセプトがブロックされていることに関して、タイムアウトで期限切れになるようにソケット/アクセプターにオプションを設定する必要があります。 accept呼び出しが戻ったら、ループを中断するか(ループ条件が偽の場合)、新しいタイムアウトを使用してaccept
を再度呼び出します。
タイムアウト値は妥協点になります。タイムアウトが小さいと、計算量が多くなり(CPUをビジー状態に保ちます)、応答性の高いスレッド関数(スレッドを停止してもあまりブロックされない関数)が得られます。