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; }
}
相关推荐
SunnyDays10112 小时前
如何使用 C# 高效实现 Excel 与 CSV 的互相转换
c#·excel·csv
Byron Loong2 小时前
【网络】C#TCP 通讯
网络·tcp/ip·c#
geovindu2 小时前
密码进行加盐哈希 using CSharp,Python,Go,Java
java·python·golang·c#·哈希算法
傻啦嘿哟2 小时前
Python 操作 Word 文档属性与字数统计方法详解
开发语言·c#
.NET修仙日记3 小时前
2026 .NET 面试八股文:高频题 + 答案 + 原理(基础核心篇)
云原生·面试·职场和发展·c#·.net·面试题·微软技术
君莫愁。3 小时前
【Unity】解决UGUI的Button无法点击/点击无反应的排查方案
unity·c#·游戏引擎·解决方案·ugui·按钮·button
石榴树下的七彩鱼13 小时前
图片修复 API 接入实战:网站如何自动去除图片水印(Python / PHP / C# 示例)
图像处理·后端·python·c#·php·api·图片去水印
忒可君14 小时前
C# winform 自制分页功能
android·开发语言·c#
南無忘码至尊14 小时前
Unity学习90天 - 第 6天 - 学习协程 Coroutine并实现每隔 2 秒生成一波敌人
学习·unity·c#·游戏引擎