返回首页

gRPC IPC 用于 .NET 桌面应用:分离 UI 逻辑

本文描述了通过 gRPC 和 IPC 分离 UI 和业务逻辑的 .NET 桌面应用架构。无头后端确保可靠性,精简客户端确保 UX。proto、Rx.NET 和进程生命周期示例。

.NET 中的 gRPC 和 IPC:无单体可靠桌面架构
Advertisement 728x90

使用gRPC与IPC在.NET桌面应用中分离UI与业务逻辑

在WPF或Avalonia UI桌面应用中,业务逻辑通常与UI线程紧密耦合。渲染卡顿或XAML崩溃会导致整个系统停滞:计时器重置、API请求中断、状态丢失。这对于智能家居管理、进程拦截或媒体播放器等后台任务尤为关键。

解决方案是将应用拆分为无头后端(Worker Service)和轻量客户端(UI)。两者通过gRPC进行服务器端流式通信,确保进程独立性。

架构:双进程,安全通信

后端(Axorith.Host)——一个.NET Worker Service,构建为WinExe。负责:

Google AdInline article slot
  • 存储会话状态。
  • 计时器和模块编排。
  • 与Home Assistant、Spotify、ETW进程监控集成。
  • 通过命名管道管理浏览器。

空闲消耗:20–30 MB内存。自主运行,独立于UI。

前端(Axorith.Client)基于Avalonia UI和ReactiveUI。仅负责可视化和输入。UI可在任务管理器中终止——后端继续运行。

层级依赖:

Google AdInline article slot
  • 客户端和主机引用Axorith.Contracts(gRPC proto)。
  • 共享核心用于会话引擎。
  • 共享用于工具和平台相关代码。
  • 模块(插件)依赖于Sdk。

使用gRPC服务器端流实现响应式

选择gRPC因其protobuf契约和流式传输能力。用于设置更新的Proto:

syntax = "proto3";

package axorith.contracts;

service ModulesService {
    rpc StreamSettingUpdates (StreamSettingUpdatesRequest) returns (stream SettingUpdate);
}

message SettingUpdate {
    string module_instance_id = 1;
    string setting_key = 2;
    SettingProperty property = 3;

    oneof value {
        string string_value = 4;
        bool bool_value = 5;
        int32 int_value = 6;
        double number_value = 7;
        ChoiceList choice_list = 8;
    }
}

在主机端:SettingUpdateBroadcaster使用Rx.NET Subject。模块中的更改(如曲目切换)被推送到流中。

在客户端:启动时打开流,更新传递到ViewModel。ReactiveUI确保即时重绘无延迟。

Google AdInline article slot

相比轮询的优势:

  • 无延迟(推送而非轮询)。
  • 高效利用流量。
  • 强类型protobuf防止不同步。

使用安全IPC替代TCP

本地端口存在风险:冲突、病毒访问、防火墙弹窗。改用IPC:

| 平台 | 传输 | 访问控制列表 |

|-----------|-----------|-----|

| Windows | 命名管道(ListenNamedPipe) | 仅限当前用户 |

| Linux/macOS | Unix域套接字(ListenUnixSocket) | 文件权限 |

主机将端点写入%AppData%/Axorith/host-info.json。客户端读取并连接。实现完全进程隔离。

生命周期与用户体验

客户端优先方法:

  • 启动Client.exe。
  • 检查host-info.json,自动在后台启动Host。
  • 关闭窗口——最小化到托盘(--tray模式)。
  • 托盘图标用于重启/停止Host或恢复UI。

连接中断检测:HTTP/2 Keep-Alive检测流中断。主机发送系统通知(Windows Toast / D-Bus)。

韧性测试:

  • “工作”会话:Spotify播放,YouTube被拦截。
  • 在任务管理器中终止Client。
  • 结果:后端存活,会话继续。

实现挑战

  • 契约: 每次更改都需要重新生成proto,更新两端。
  • 版本控制: gRPC拦截器检查x-axorith-version。不匹配导致FailedPrecondition + 自动更新。
  • 异步: 所有调用基于Task,处理超时和本地网络错误。

关键要点

  • 进程分离消除了UI线程的单点故障。
  • gRPC流式传输 + Rx.NET实现无需轮询的响应式UI。
  • IPC(命名管道/UDS)确保安全,无需端口。
  • 客户端优先的UX向用户隐藏复杂性。
  • 适用于需要系统管理的24/7应用。

— Editorial Team

Advertisement 728x90

继续阅读