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

C#命名管道首次连接正常,二次触发报System.ObjectDisposedException错误

问题根源

你把NamedPipeServerStream、StreamReader、StreamWriter都声明成了类的公共字段,第一次点击按钮执行完后,finally块里已经把这些对象全部释放了。第二次点击按钮时,你还是试图复用这些已经被Dispose的实例,自然就抛出ObjectDisposedException了。

修复方案

核心思路是每次点击按钮都创建全新的管道实例,不要复用已释放的对象,同时用更安全的异步写法和资源管理方式:

关键改动点

  • 把管道相关变量从类级字段移到server_named_pipe方法内部,每次调用都创建新实例
  • 用await pipeServer.WaitForConnectionAsync(stoppingToken)替代旧的Begin/End异步模式,避免回调里的资源引用问题
  • 用using语句自动管理对象生命周期,不用手动调用Dispose
  • 创建管道时直接传入权限设置,避免后续操作失效

修改后的完整代码

public string test = "";

// 按钮点击执行的方法
public void pipe_server()
{
    var source = new CancellationTokenSource();
    _ = server_named_pipe(source.Token); // 用_避免async void警告,可按需处理Task
}

protected async Task server_named_pipe(CancellationToken stoppingToken)
{
    // 1. 配置管道安全权限
    var pipeSecurity = new PipeSecurity();
    var worldSid = new System.Security.Principal.SecurityIdentifier(System.Security.Principal.WellKnownSidType.WorldSid, null);
    var accessRule = new PipeAccessRule(worldSid, PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
    pipeSecurity.AddAccessRule(accessRule);

    // 2. 每次调用创建新管道实例,using自动释放资源
    using var pipeServer = new NamedPipeServerStream(
        "testpipe", 
        PipeDirection.InOut, 
        1, 
        PipeTransmissionMode.Message, 
        PipeOptions.Asynchronous, 
        20, 
        20,
        pipeSecurity);

    using var streamReader = new StreamReader(pipeServer);
    using var streamWriter = new StreamWriter(pipeServer);
    streamWriter.AutoFlush = true; // 自动刷新输出流

    try
    {
        // 3. 异步等待连接,同时处理超时
        var connectTask = pipeServer.WaitForConnectionAsync(stoppingToken);
        if (await Task.WhenAny(connectTask, Task.Delay(5000, stoppingToken)) == connectTask)
        {
            await connectTask; // 确认连接成功

            // 4. 直接在流程内处理数据传输
            await streamWriter.WriteLineAsync("Waiting");
            await pipeServer.WaitForPipeDrainAsync();
            
            test = await streamReader.ReadLineAsync();
            using var logWriter = File.AppendText(CommonClass.error_path);
            await logWriter.WriteLineAsync($"Named_Pipe_message:  {test} {DateTime.Now}");
        }
        else
        {
            // 超时提示,可按需扩展
            Console.WriteLine("连接超时");
        }
    }
    catch (OperationCanceledException)
    {
        // 处理令牌取消的情况
    }
    catch (Exception ex)
    {
        if (pipeServer.IsConnected)
        {
            await pipeServer.WaitForPipeDrainAsync();
            pipeServer.Disconnect();
        }
        // 可添加异常日志记录
    }
    // using块自动释放所有资源,无需手动Dispose
}

额外说明

  • 原有的PipeConnected回调被整合到异步流程中,避免了回调引用外部已释放资源的问题
  • 用Task.WhenAny实现超时等待,更符合async/await的异步编程范式
  • streamWriter.AutoFlush = true省去了每次写入后手动Flush的操作
  • 区分了取消令牌触发的异常,避免误判业务异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 23:30:14