C#命名管道服务端如何设置连接等待超时?
解决NamedPipeServerStream等待连接超时问题
要实现5秒超时停止等待,核心是替换阻塞的WaitForConnection()调用,改用支持超时控制的异步等待方式,以下是两种可行方案:
方案一:使用异步方法+超时任务(推荐,适配多数.NET版本)
利用WaitForConnectionAsync()结合Task.WhenAny实现超时控制,代码修改如下:
public async void server_named_pipe() { const int ConnectionTimeoutMs = 5000; // 5秒超时 string test = ""; do { NamedPipeServerStream pipeServer = null; StreamReader sr = null; StreamWriter sw = null; try { pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous, 20, 20); sr = new StreamReader(pipeServer); sw = new StreamWriter(pipeServer); // 同时等待连接任务和超时任务 var connectTask = pipeServer.WaitForConnectionAsync(); var timeoutTask = Task.Delay(ConnectionTimeoutMs); var completedTask = await Task.WhenAny(connectTask, timeoutTask); if (completedTask == timeoutTask) { // 超时触发,关闭管道并终止等待 pipeServer.Close(); Console.WriteLine("连接超时,停止等待"); break; } // 连接成功,执行后续通信逻辑 await connectTask; sw.WriteLine("Waiting"); await sw.FlushAsync(); await pipeServer.WaitForPipeDrainAsync(); test = await sr.ReadLineAsync(); } catch (Exception ex) { Console.WriteLine($"连接或通信异常: {ex.Message}"); } finally { sw?.Dispose(); sr?.Dispose(); pipeServer?.Dispose(); } } while (string.IsNullOrEmpty(test)); }
关键说明:
- 将管道、流的创建逻辑移入循环内部,避免单次资源释放后无法复用
- 通过
Task.WhenAny实现“连接/超时”二选一的逻辑,精准控制等待时长 - 超时后必须主动关闭管道,避免系统资源泄漏
- 统一使用异步版本的IO方法,保持代码逻辑一致性
方案二:使用旧版异步模型(适配.NET Framework 4.0及更早版本)
如果项目基于较老的.NET Framework,可使用BeginWaitForConnection结合WaitHandle.WaitOne设置超时:
public void server_named_pipe() { const int ConnectionTimeoutMs = 5000; string test = ""; do { NamedPipeServerStream pipeServer = null; StreamReader sr = null; StreamWriter sw = null; try { pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous, 20, 20); sr = new StreamReader(pipeServer); sw = new StreamWriter(pipeServer); // 启动异步等待连接 IAsyncResult asyncResult = pipeServer.BeginWaitForConnection(null, null); // 等待5秒,判断连接是否完成 if (!asyncResult.AsyncWaitHandle.WaitOne(ConnectionTimeoutMs)) { pipeServer.Close(); Console.WriteLine("连接超时,停止等待"); break; } // 完成异步连接操作 pipeServer.EndWaitForConnection(asyncResult); sw.WriteLine("Waiting"); sw.Flush(); pipeServer.WaitForPipeDrain(); test = sr.ReadLine(); } catch (Exception ex) { Console.WriteLine($"连接或通信异常: {ex.Message}"); } finally { sw?.Dispose(); sr?.Dispose(); pipeServer?.Dispose(); } } while (string.IsNullOrEmpty(test)); }
关键说明:
- 通过
BeginWaitForConnection启动异步等待,获取对应的等待句柄 - 调用
WaitOne(ConnectionTimeoutMs)设置超时阈值,返回值表示是否在超时前完成连接 - 超时后必须关闭管道,避免占用系统句柄资源
- 连接成功后必须调用
EndWaitForConnection完成异步操作流程
内容的提问来源于stack exchange,提问作者Mdarende
相关产品推荐
相关产品推荐

