在Windows C ++服务中阻止两个线程

时间:2014-09-24 06:29:19

标签: c++ windows multithreading service tcpserver

我有一个用C ++编写的Windows服务,它充当TCP服务器,用于侦听传入连接。

我初始化了服务器套接字并将accept代码放在一个单独的线程中。这将接受并处理传入的连接。

但是,我还需要在服务收到STOP信号时停止此线程。所以我想到了使用CreateEvent创建一个事件对象并等待它发出信号。这种等待将在创建接受线程的线程中发生。所以我可以使用TerminateThread函数在收到STOP信号时停止接受线程。

然而,MSDN表示

  

TerminateThread是一个危险的函数,只能在最极端的情况下使用。

应该严格遵循这一点,我的方法是否正确?这可能是另一种方式吗?

2 个答案:

答案 0 :(得分:2)

在Windows中,只需拨打accept即可从其他线程唤醒阻止closesocket来电。阻塞accept调用将返回-1,并且您的代码有机会通过检查已设置的其他退出条件(例如全局变量)来突破其所处的循环

这也适用于具有close功能的Mac(以及可能的BSD衍生产品),但不适用于Linux。针对此问题的更通用的UNIX解决方案是here

以下Windows解决方案的一些pseduo代码。

SOCKET _listenSocket;
bool _needToExit = false;
HANDLE _hThread;

void MakeListenThreadExit()
{
   _needToExit = true;
   closesocket(_listenSocket);
   _listenSocket = INVALID_SOCKET;

   // wait for the thread to exit
   WaitForSingleObject(_hThread, INFINITE);       
}

DWORD __stdcall ListenThread(void* context)
{
    while (_needToExit == false)
    {            
        SOCKET client = accept(_listenSocket, (sockaddr*)&addr, &addrSize);
        if ((client == -1) || _needToExit)
        {
            break;
        } 
        ProcessClient(client);
    }    
    return 0;
}

答案 1 :(得分:1)

在这种情况下,请勿在阻塞套接字上使用accept()。请改用非阻塞套接字。然后您可以使用select()超时,以便您的线程可以定期检查终止条件。或者更好的是,将WSACreateEvent()WSASelectEvent()一起使用。创建两个事件对象,一个用于检测客户端连接,另一个用于检测线程终止。然后,您可以使用WSAWaitForMultipleEvents()同时等待这两个事件。在需要时使用WSASetEvent()表示终止事件,并在发出其他事件信号时致电accept()WSAAccept()WSAWaitForMultipleEvents()会告诉您要采取行动的事件。