Zurück zur Startseite

gRPC IPC für .NET-Desktops: Trennung der UI-Logik

Der Artikel beschreibt die Architektur einer .NET-Desktop-Anwendung mit Trennung von UI- und Geschäftslogik über gRPC und IPC. Headless Backend gewährleistet Zuverlässigkeit, Thin Client — UX. Beispiele für Proto, Rx.NET und Prozesslebenszyklus.

gRPC und IPC in .NET: zuverlässige Desktop-Architektur ohne Monolith
Advertisement 728x90

Trennung von UI und Geschäftslogik in .NET-Desktop-Apps mit gRPC und IPC

In WPF- oder Avalonia-UI-Desktopanwendungen ist die Geschäftslogik eng mit dem UI-Thread gekoppelt. Rendering-Hänger oder XAML-Abstürze bringen das gesamte System zum Stillstand: Timer werden zurückgesetzt, API-Anfragen unterbrochen und Zustände gehen verloren. Dies ist kritisch für Hintergrundaufgaben wie Smart-Home-Verwaltung, Prozessblockierung oder Mediaplayer.

Die Lösung ist die Aufteilung in ein headless Backend (Worker Service) und einen schlanken Client (UI). Sie kommunizieren über gRPC mit serverseitigem Streaming, was Prozessunabhängigkeit gewährleistet.

Architektur: Zwei Prozesse, sichere Kommunikation

Backend (Axorith.Host) – ein .NET Worker Service, als WinExe gebaut. Verantwortlich für:

Google AdInline article slot
  • Speichern des Sitzungszustands.
  • Timer und Modul-Orchestrierung.
  • Integration mit Home Assistant, Spotify, ETW-Prozessüberwachung.
  • Browser-Verwaltung über Named Pipes.

Leerlaufverbrauch: 20–30 MB RAM. Läuft autonom, unabhängig von der UI.

Frontend (Axorith.Client) auf Avalonia UI mit ReactiveUI. Nur Visualisierung und Eingabe. Die UI kann im Task-Manager beendet werden – das Backend läuft weiter.

Schichtenabhängigkeiten:

Google AdInline article slot
  • Client und Host referenzieren Axorith.Contracts (gRPC proto).
  • Shared Core für die Sitzungs-Engine.
  • Shared für Utilities und plattformabhängigen Code.
  • Module (Plugins) hängen vom Sdk ab.

gRPC mit serverseitigem Streaming für Reaktivität

gRPC wird für Protobuf-Verträge und Streaming gewählt. Proto für Einstellungsaktualisierungen:

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;
    }
}

Auf dem Host: SettingUpdateBroadcaster mit Rx.NET Subject. Änderungen in Modulen (z.B. Track-Wechsel) werden in den Stream gepusht.

Auf dem Client: Ein Stream wird beim Start geöffnet, Aktualisierungen gehen an das ViewModel. ReactiveUI sorgt für sofortiges Neuzeichnen ohne Verzögerung.

Google AdInline article slot

Vorteile gegenüber Polling:

  • Keine Verzögerungen (Push statt Polling).
  • Effiziente Verkehrsnutzung.
  • Starke Protobuf-Typisierung verhindert Desynchronisierung.

Sichere IPC statt TCP

Lokale Ports sind anfällig: Konflikte, Virenzugriff, Firewall-Pop-ups. Umstellung auf IPC:

| Plattform | Transport | ACL |

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

| Windows | Named Pipes (ListenNamedPipe) | Nur aktueller Benutzer |

| Linux/macOS | Unix Domain Sockets (ListenUnixSocket) | Dateiberechtigungen |

Der Host schreibt den Endpunkt in %AppData%/Axorith/host-info.json. Der Client liest und verbindet sich. Vollständige Prozessisolierung.

Lebenszyklus und UX

Client-zuerst-Ansatz:

  • Client.exe starten.
  • host-info.json prüfen, Host automatisch im Hintergrund starten.
  • Fenster schließen – in Tray minimieren (--tray-Modus).
  • Tray-Icon für Neustart/Stopp des Hosts oder Wiederherstellung der UI.

Verbindungsabbruch-Erkennung: HTTP/2 Keep-Alive erkennt Stream-Unterbrechungen. Der Host sendet eine Systembenachrichtigung (Windows Toast / D-Bus).

Resilienz-Test:

  • "Arbeits"-Sitzung: Spotify spielt, YouTube blockiert.
  • Client im Task-Manager beenden.
  • Ergebnis: Backend lebt, Sitzung läuft weiter.

Implementierungsherausforderungen

  • Verträge: Jede Änderung erfordert Regenerierung des Proto, Aktualisierung beider Seiten.
  • Versionierung: gRPC Interceptor prüft x-axorith-version. Fehlende Übereinstimmung führt zu FailedPrecondition + automatischem Update.
  • Asynchronität: Alle Aufrufe sind Task-basiert, behandeln Timeouts, Netzwerkfehler auf localhost.

Wichtige Erkenntnisse

  • Prozess-Trennung beseitigt Single Point of Failure im UI-Thread.
  • gRPC-Streaming + Rx.NET liefern reaktive UI ohne Polling.
  • IPC (Named Pipes/UDS) gewährleistet Sicherheit ohne Ports.
  • Client-zuerst-UX verbirgt Komplexität vor dem Benutzer.
  • Geeignet für 24/7-Anwendungen mit Systemverwaltung.

— Editorial Team

Advertisement 728x90

Weiterlesen