C#进程通讯-命名管道通讯

目录

客户端代码

csharp 复制代码
Task.Run(() =>
            {
                List<string> result = new List<string>();

                try
                {
                    using (var client = new NamedPipeClientStream(".", "MyTranslatePipe", PipeDirection.InOut))
                    {
                        // 记录连接开始(便于调试)
                        System.Diagnostics.Debug.WriteLine("NamedPipe: Connecting...");
                        // 5 秒超时(根据需要调整)
                        client.Connect(5000);
                        System.Diagnostics.Debug.WriteLine($"NamedPipe: Connected = {client.IsConnected}");

                        if (!client.IsConnected)
                        {
                            throw new InvalidOperationException("未能连接到命名管道。请确认服务已启动。");
                        }

                        // 明确使用不带 BOM 的 UTF8,避免可能的前导字节问题
                        var noBomUtf8 = new System.Text.UTF8Encoding(encoderShouldEmitUTF8Identifier: false);

                        // 使用 leaveOpen:true,避免 StreamReader/StreamWriter 在 Dispose 时关闭底层 pipe
                        using (var writer = new StreamWriter(client, noBomUtf8, bufferSize: 1024, leaveOpen: true) { AutoFlush = true })
                        using (var reader = new StreamReader(client, noBomUtf8, detectEncodingFromByteOrderMarks: false, bufferSize: 1024, leaveOpen: true))
                        {
                            System.Diagnostics.Debug.WriteLine("NamedPipe: Writing request...");
                            writer.WriteLine(json);
                            writer.Flush();

                            System.Diagnostics.Debug.WriteLine("NamedPipe: Waiting for response...");
                            // 阻塞读取一行响应(服务端必须 WriteLine 返回)
                            string resultJson = reader.ReadLine();
                            System.Diagnostics.Debug.WriteLine("NamedPipe: Received response");

                            if (string.IsNullOrEmpty(resultJson))
                            {
                                // 防护:避免反序列化 null 抛异常
                                result = new List<string>();
                            }
                            else
                            {
                                result = JsonConvert.DeserializeObject<List<string>>(resultJson) ?? new List<string>();
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    // 记录并用简单回退策略,不抛到 UI 线程导致不可预期的问题
                    System.Diagnostics.Debug.WriteLine("NamedPipe error: " + ex);
                    try
                    {
                        // 在 AutoCAD 环境建议用 Editor.WriteMessage 打日志(此处用 MessageBox 仅作提示)
                        System.Windows.MessageBox.Show("翻译服务通信失败:" + ex.Message, "提示");
                    }
                    catch { /* 若线程上下文不能弹窗则忽略 */ }

                    // 回退到原文,保证不会返回 null
                    result = texts.ToList();
                }

                return result;
            });

服务端

csharp 复制代码
using Newtonsoft.Json;
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;
using TextTranslate;

Console.WriteLine("Named pipe server starting...");

string pipeName = "MyTranslatePipe";

// 使用异步主循环,持续接受客户端连接
while (true)
{
    // 为每次连接创建新的 NamedPipeServerStream,但不要在外层 using,这样不会在启动后台任务后立即被释放
    var server = new NamedPipeServerStream(
        pipeName,
        PipeDirection.InOut,
        NamedPipeServerStream.MaxAllowedServerInstances,
        PipeTransmissionMode.Byte,
        PipeOptions.Asynchronous);

    Console.WriteLine("等待 .NET Framework 客户端连接...");
    await server.WaitForConnectionAsync();
    Console.WriteLine("客户端已连接。");

    // 为当前连接启动一个后台任务来处理(任务内部负责释放 server)
    _ = Task.Run(async () =>
    {
        // 将 server 的释放放到任务内部 using,确保后台任务结束后再释放
        using (server)
        {
            try
            {
                var noBomUtf8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);

                // 使用 leaveOpen:true,防止 reader/writer 在 Dispose 时关闭底层 NamedPipeServerStream
                using var reader = new StreamReader(server, noBomUtf8, detectEncodingFromByteOrderMarks: false, bufferSize: 1024, leaveOpen: true);
                using var writer = new StreamWriter(server, noBomUtf8, bufferSize: 1024, leaveOpen: true) { AutoFlush = true };

                while (server.IsConnected)
                {
                    string? request = await reader.ReadLineAsync();

                    if (request == null)
                    {
                        Console.WriteLine("客户端已断开连接(read null)。");
                        break;
                    }

                    if (string.IsNullOrEmpty(request) || request.Equals("exit", StringComparison.OrdinalIgnoreCase))
                    {
                        Console.WriteLine("收到退出指令,关闭连接。");
                        break;
                    }

                    Console.WriteLine($"收到请求: {request}");

                    string result = Translate(request);

                    await writer.WriteLineAsync(result);
                    Console.WriteLine($"返回结果: {result}");
                }

                // 确保所有写入被刷新到管道
                try { writer.Flush(); } catch { }
            }
            catch (Exception ex)
            {
                Console.WriteLine("处理客户端时发生异常: " + ex);
            }
            finally
            {
                // 显式断开连接(断开前 reader/writer 已被 Dispose,但 leaveOpen:true 不会关闭底层 stream)
                try { if (server.IsConnected) server.Disconnect(); } catch { }
                Console.WriteLine("处理任务结束,准备接受下一个连接。");
            }
        }
    });
}

static string Translate(string input)
{
    TranslationRequest? translationRequest = JsonConvert.DeserializeObject<TranslationRequest>(input);
    Task<List<string>> task = translationRequest.Texts.Translate(translationRequest.TargetLanguage);
    task.Wait();
    return JsonConvert.SerializeObject(task.Result);
    //return JsonConvert.SerializeObject(new List<string>() { "苹果" });

}

// 内部请求模型(与服务端保持一致)
public class TranslationRequest
{
    public List<string> Texts { get; set; }
    public string TargetLanguage { get; set; }
}
相关推荐
淡海水3 小时前
08-03-不可变-ImmutableDictionary-TKey-TValue-与ImmutableHashSet-T-持久化哈希树
数据结构·算法·c#·哈希算法·dictionary·immutable
典典分享指南6 小时前
一品牌多产品线的 GEO 内容矩阵:从策略到落地
java·c#·bash·symfony
今夜有雨.6 小时前
C# 学习文档(零基础入门)
开发语言·学习·c#
软件黑马王子7 小时前
14.事件中心:主要作用和原理
开发语言·前端框架·c#
海盗123411 小时前
微软技术周报 2026-08-31~09-07:GPT-6 Astra 登陆 Foundry、M365 全球认证故障复盘、C# 15 封闭层级
gpt·microsoft·c#
reasonsummer12 小时前
【办公类-115-01】20260906育儿知识(家园小报)批量制作(2026年9月-2027年6月)
开发语言·数据库·c#
软件黑马王子13 小时前
13.缓存池优化:对象上限配置
开发语言·前端框架·c#
唐青枫13 小时前
C#.NET StructureMap 从依赖注入到项目实战
c#·.net
fujisheng66114 小时前
FUI 编译期装配实践:从反射注册到 Source Generator
c#·unity3d
智码看视界14 小时前
.NET 10 推理大模型TensorSharp 3.3.0 部署实测:纯.NET推理引擎反超llama.cpp 1.5倍,DFlash2提速62%
c#·.net·llama.cpp·.net 10·tensorsharp·本地大模型推理·开源推理引擎