You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多线程命名管道服务器并行处理请求异常问题排查

多线程命名管道服务器并行处理问题

我正在尝试创建一个可并行处理多个请求的多线程命名管道服务器,但运行行为不符合预期:当当前请求处于处理繁忙状态时,新请求会抛出"访问路径被拒绝"错误,直到当前执行线程释放。

代码实现

using Newtonsoft.Json;
using System;
using System.IO;
using System.IO.Pipes;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
using System.Threading;

namespace API.PipeServer
{
    public class Server
    {
        private bool running;
        private Thread runningThread;
        private EventWaitHandle terminateHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
        public string PipeName { get; set; }

        private void ServerLoop()
        {
            while (running)
            {
                ProcessNextClient();
            }

            terminateHandle.Set();
        }

        public void Run()
        {
            running = true;
            runningThread = new Thread(ServerLoop);
            runningThread.Start();
        }

        public void Stop()
        {
            running = false;
            terminateHandle.WaitOne();
        }

        public virtual string ProcessRequest(string message)
        {
            return "";
        }

        public void ProcessClientThread(object o)
        {
            using (NamedPipeServerStream pipeStream = (NamedPipeServerStream)o)
            {
                StreamReader sr = new StreamReader(pipeStream);

                //Receive instruction message
                string instructionJson = sr.ReadLine();
                Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: --- Receiving Instruction ---");
                Console.WriteLine(instructionJson);

                //Getting instruction message
                var instruction = JsonConvert.DeserializeObject<InstructionHandler.Instruction>(instructionJson);

                //Get data
                var json = API.API.GetAPIJson(instruction);

                //Send data back to Python client
                try
                {
                    pipeStream.Write(Encoding.UTF8.GetBytes(json));
                    pipeStream.WaitForPipeDrain();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }

                Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: --- Closing Stream ---");

                pipeStream.Close();
                pipeStream.Dispose();
            }
        }

        public void ProcessNextClient()
        {
            try
            {
                Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: Creating server");
                PipeSecurity pipeSecurity = new PipeSecurity();
                pipeSecurity.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), PipeAccessRights.ReadWrite, AccessControlType.Allow));

                var pipeStream = NamedPipeServerStreamAcl.Create("test_api", PipeDirection.InOut, 254, PipeTransmissionMode.Message, PipeOptions.None, 1024, 1024, pipeSecurity);

                pipeStream.WaitForConnection();

                //Spawn a new thread for each request and continue waiting
                Thread t = new Thread(ProcessClientThread);
                t.Start(pipeStream);
            }
            catch (Exception e)
            {
                Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: Error - {e.Message}");
            }
        }
    }
}

典型输出

典型输出


问题分析与解决方法

1. 管道名格式错误

命名管道的标准格式应为\\.\pipe\管道名,直接使用"test_api"作为管道名,虽然系统会自动补全,但可能在多实例创建时引发路径识别问题,导致新连接无法创建实例。

修复:将管道创建代码中的名称改为标准格式:

var pipeStream = NamedPipeServerStreamAcl.Create(@"\\.\pipe\test_api", PipeDirection.InOut, 254, PipeTransmissionMode.Message, PipeOptions.None, 1024, 1024, pipeSecurity);

2. StreamReader导致底层流提前关闭

创建StreamReader时未指定leaveOpen: true,默认情况下StreamReader释放时会关闭底层的pipeStream,而using块又会再次释放管道流,导致双重释放,可能引发管道状态异常。

修复:创建StreamReader时添加leaveOpen: true参数:

StreamReader sr = new StreamReader(pipeStream, Encoding.UTF8, true, 1024, leaveOpen: true);

3. 多余的流释放代码

using块会自动处理pipeStream的释放,手动调用pipeStream.Close()和pipeStream.Dispose()属于重复操作,可能导致流状态异常。

修复:移除这两行代码:

// pipeStream.Close();
// pipeStream.Dispose();

4. 可选优化:使用ThreadPool替代手动创建线程

手动创建线程的开销较高,建议使用ThreadPool.QueueUserWorkItem或Task.Run来处理客户端连接,提升性能:

// 替换原线程创建代码
ThreadPool.QueueUserWorkItem(ProcessClientThread, pipeStream);
// 或者使用Task
Task.Run(() => ProcessClientThread(pipeStream));

内容的提问来源于stack exchange,提问作者ceds

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 13:15:38