命名管道:许多客户。如何谨慎创建线程?线程池?

时间:2010-08-12 07:34:18

标签: multithreading winapi ipc named-pipes threadpool

情况:

我正在使用C ++在Windows上使用命名管道。

服务器通过CreateNamedPipe创建命名管道实例,并等待客户端通过ConnectNamedPipe进行连接。

每次客户端调用CreateFile来访问命名管道时,服务器都会使用CreateThread创建一个线程来为该客户端提供服务。之后,服务器重复循环,通过CreateNamedPipe创建管道实例,并通过ConnectNamedPipe等监听下一个客户端......

问题:

每个客户端请求都会在服务器上触发CreateThread。如果客户端变得快速而激烈,那么会有很多调用CreateThread。

问题:

Q1:是否可以重用已创建的线程来为未来的客户端请求提供服务? 如果可以,我该怎么做?

Q2:线程池会在这种情况下提供帮助吗?

2 个答案:

答案 0 :(得分:3)

我今天使用IOCompletion端口编写了一个命名管道服务器,只是为了看看如何。

基本逻辑流程是:

  • 我通过CreateNamedPipe创建了第一个命名管道
  • 我使用该句柄创建了主要的Io Completion Port对象:CreateIoCompletionPort
  • 我创建了一个工作线程池 - 作为一个拇指吮吸,CPU x2。每个工作线程都在一个循环中调用GetQueuedCompletionStatus。
  • 然后调用ConnectNamedPipe传递重叠结构。当此管道连接时,其中一个GetQueuedCompletionStatus调用将返回。
  • 我的主线程然后通过调用GetQueuedCompletionStatus来加入工作池。

真的是这样。

每次线程从GetQueuedCompletionStatus返回时,因为关联的管道已连接,已读取数据或已关闭。 每次连接管道时,我立即创建一个未连接的管道来接受下一个客户端(一次可能有多个等待)并在当前管道上调用ReadFile,传递重叠结构 - 确保数据到达时GetQueuedCompletionStatus将告诉我它。

有一些令人恼火的边缘情况,其中函数返回失败代码,但GetLastError()是成功的。由于功能“失败”,您必须立即处理成功,因为没有发布排队完成状态。相反,(我相信Vista添加了一个API来“修复”这个)如果数据立即可用,重叠的函数可以返回成功,但是排队的完成状态也是如此,所以在这种情况下注意不要双重处理数据。 / p>

答案 1 :(得分:1)

在Windows上,构建并发服务器的最有效方法是使用带有完成端口的异步模型。但是,你可以使用线程池并使用阻塞i / o,因为这是一个更简单的编程抽象。

Vista / Windows 2008提供线程池抽象。