两个自研C#应用间传递字符串值的低复杂度方案咨询
C# 双进程跨进程获取文本框值的低复杂度实现方案
你当前使用的文件中转方案存在磁盘IO开销高、易触发文件占用冲突、实时性差的问题,以下是几种实现成本极低、原生支持的方案,按需选择即可。
方案1:内存映射文件(实现复杂度最低,最适配你现有逻辑)
该方案将共享数据存在系统内存而非磁盘,代码逻辑和文件读写几乎一致,无磁盘IO开销,不存在文件锁问题,是替换文件中转方案的最优选择,.NET Framework 4.0+、.NET Core 3.0+全版本原生支持。
注意:共享内存的命名建议加项目专属前缀,避免和其他程序创建的同名内存块冲突
应用A(数据提供方)核心代码:// 程序启动时初始化一次共享内存块即可,名称全局唯一 using var sharedMemory = MemoryMappedFile.CreateOrOpen("MyApp_AppATextBoxShare", 2048); // 容量按需调整,普通文本框2KB足够 // 挂到TextBox的TextChanged事件,内容变化时写入共享内存 private void SyncTextBoxToMemory() { using var writer = sharedMemory.CreateViewAccessor(); byte[] textBuffer = Encoding.UTF8.GetBytes(targetTextBox.Text); writer.Write(0, textBuffer.Length); // 先写入字符串长度,方便读取端识别边界 writer.WriteArray(4, textBuffer, 0, textBuffer.Length); }应用B(数据读取方)核心代码:
// 直接打开已存在的共享内存块 using var sharedMemory = MemoryMappedFile.OpenExisting("MyApp_AppATextBoxShare"); private string ReadTextBoxFromMemory() { using var reader = sharedMemory.CreateViewAccessor(); int textLen = reader.ReadInt32(0); byte[] textBuffer = new byte[textLen]; reader.ReadArray(4, textBuffer, 0, textLen); return Encoding.UTF8.GetString(textBuffer); } // 需要刷新值时调用ReadTextBoxFromMemory即可,加个百毫秒级的定时器轮询也几乎无性能开销方案2:命名管道(实时性最优,无需轮询)
如果需要文本内容变化时自动同步到应用B,不想做轮询,用命名管道是最省事的原生方案,基于流通信,支持主动推送。
应用A(管道服务端)核心代码:// 程序启动时开启管道监听 private async void StartPipeHost() { var pipeServer = new NamedPipeServerStream("MyApp_AppATextPipe"); await pipeServer.WaitForConnectionAsync(); // TextChanged事件触发时主动推送最新文本 private void OnTextBoxUpdated(object sender, EventArgs e) { byte[] textBuffer = Encoding.UTF8.GetBytes(targetTextBox.Text); pipeServer.Write(BitConverter.GetBytes(textBuffer.Length), 0, 4); pipeServer.Write(textBuffer, 0, textBuffer.Length); pipeServer.Flush(); } }应用B(管道客户端)核心代码:
private async void ConnectPipe() { var pipeClient = new NamedPipeClientStream(".", "MyApp_AppATextPipe", PipeDirection.In); await pipeClient.ConnectAsync(); // 持续监听服务端推送的新内容 while (true) { byte[] lenBuffer = new byte[4]; await pipeClient.ReadExactlyAsync(lenBuffer, 0, 4); int textLen = BitConverter.ToInt32(lenBuffer, 0); byte[] textBuffer = new byte[textLen]; await pipeClient.ReadExactlyAsync(textBuffer, 0, textLen); string aTextBoxValue = Encoding.UTF8.GetString(textBuffer); // 拿到值直接做后续业务处理即可 } }不推荐优先选的方案
WM_COPYDATA消息、COM接口、第三方RPC组件这类方案要么需要调用Win32 API写更多样板代码,要么需要引入额外依赖,实现复杂度高于上述两个方案,仅在有特殊系统兼容需求时考虑。
选型建议:
如果想最少改动现有逻辑,直接把文件读写替换成内存映射文件即可,整体代码改动量不超过10行;如果需要内容变化实时同步,直接用命名管道。不要继续用本地文件中转,多进程并发读写时很容易抛出文件占用异常,还需要额外处理临时文件残留、磁盘写入失败的边缘问题。
内容的提问来源于stack exchange,提问作者dome_engineer
相关产品推荐
相关产品推荐

