情况:
我正在使用C ++在Windows上使用命名管道。
服务器通过CreateNamedPipe创建命名管道实例,并等待客户端通过ConnectNamedPipe进行连接。
每次客户端调用CreateFile来访问命名管道时,服务器都会使用CreateThread创建一个线程来为该客户端提供服务。之后,服务器重复循环,通过CreateNamedPipe创建管道实例,并通过ConnectNamedPipe等监听下一个客户端......
问题:
每个客户端请求都会在服务器上触发CreateThread。如果客户端变得快速而激烈,那么会有很多调用CreateThread。
问题:
Q1:是否可以重用已创建的线程来为未来的客户端请求提供服务? 如果可以,我该怎么做?
Q2:线程池会在这种情况下提供帮助吗?
答案 0 :(得分:3)
我今天使用IOCompletion端口编写了一个命名管道服务器,只是为了看看如何。
基本逻辑流程是:
真的是这样。
每次线程从GetQueuedCompletionStatus返回时,因为关联的管道已连接,已读取数据或已关闭。 每次连接管道时,我立即创建一个未连接的管道来接受下一个客户端(一次可能有多个等待)并在当前管道上调用ReadFile,传递重叠结构 - 确保数据到达时GetQueuedCompletionStatus将告诉我它。
有一些令人恼火的边缘情况,其中函数返回失败代码,但GetLastError()是成功的。由于功能“失败”,您必须立即处理成功,因为没有发布排队完成状态。相反,(我相信Vista添加了一个API来“修复”这个)如果数据立即可用,重叠的函数可以返回成功,但是排队的完成状态也是如此,所以在这种情况下注意不要双重处理数据。 / p>
答案 1 :(得分:1)
在Windows上,构建并发服务器的最有效方法是使用带有完成端口的异步模型。但是,你可以使用线程池并使用阻塞i / o,因为这是一个更简单的编程抽象。
Vista / Windows 2008提供线程池抽象。