Oddělení UI a obchodní logiky v desktopových aplikacích .NET pomocí gRPC a IPC
V desktopových aplikacích na WPF nebo Avalonia UI je obchodní logika pevně svázána s UI vláknem. Zaseknutí vykreslování nebo pád XAML vede k zastavení celého systému: časovače se resetují, API požadavky se přeruší, stav se ztratí. To je kritické pro úlohy na pozadí, jako je řízení chytré domácnosti, blokování procesů nebo mediální přehrávač.
Řešením je rozdělení na headless backend (Worker Service) a tenký klient (UI). Komunikují přes gRPC se server-side streamováním, což zajišťuje nezávislost procesů.
Architektura: dva procesy, zabezpečená komunikace
Backend (Axorith.Host) – .NET Worker Service, sestavený jako WinExe. Zodpovídá za:
- Ukládání stavu relací.
- Časovače a orchestraci modulů.
- Integraci s Home Assistant, Spotify, ETW monitorování procesů.
- Řízení prohlížeče přes Named Pipes.
Spotřeba v klidu: 20–30 MB RAM. Funguje autonomně, nezávisle na UI.
Frontend (Axorith.Client) na Avalonia UI s ReactiveUI. Pouze vizualizace a vstup. UI lze ukončit ve Správci úloh – backend bude pokračovat v práci.
Závislosti vrstev:
- Client a Host odkazují na Axorith.Contracts (gRPC proto).
- Sdílené Core pro relace.
- Shared pro utility a platformně závislý kód.
- Moduly (pluginy) závisí na Sdk.
gRPC se server-side streamováním pro reaktivitu
gRPC bylo zvoleno kvůli protobuf kontraktům a streamování. Proto pro aktualizace nastavení:
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;
}
}
Na host: SettingUpdateBroadcaster s Rx.NET Subject. Změny v modulech (přepnutí skladby) se posílají do streamu.
Na client: při spuštění se otevře stream, aktualizace jdou do ViewModel. ReactiveUI zajišťuje okamžité překreslení bez lagů.
Výhody oproti pollingu:
- Žádné zpoždění (push místo dotazování).
- Efektivní využití přenosu.
- Silná typizace protobuf zabraňuje desynchronizaci.
Zabezpečené IPC místo TCP
Lokální porty jsou zranitelné: konflikty, přístup virů, firewallová upozornění. Přechod na IPC:
| Platforma | Transport | ACL |
|-----------|-----------|-----|
| Windows | Named Pipes (ListenNamedPipe) | Pouze aktuální uživatel |
| Linux/macOS | Unix Domain Sockets (ListenUnixSocket) | Práva souborů |
Host zapíše endpoint do %AppData%/Axorith/host-info.json. Client přečte a připojí se. Úplná izolace procesů.
Životní cyklus a UX
Client-first přístup:
- Spuštění Client.exe.
- Kontrola host-info.json, automatické spuštění Host na pozadí.
- Zavření okna – minimalizace do tray (--tray mode).
- Tray ikona pro restart/stop Host nebo rozbalení UI.
Detekce přerušení: HTTP/2 Keep-Alive zaznamená přerušení streamu. Host posílá systémové oznámení (Windows Toast / D-Bus).
Test nezničitelnosti:
- Relace "Práce": Spotify hraje, YouTube je zablokován.
- Kill Client ve Správci úloh.
- Výsledek: backend žije, relace pokračuje.
Obtíže implementace
- Kontrakty: Každá změna – regenerace proto, aktualizace obou stran.
- Verzování: gRPC Interceptor kontroluje
x-axorith-version. Neshoda – FailedPrecondition + automatická aktualizace. - Asynchronnost: Všechny volání Task, zpracování timeoutů, síťových chyb na localhost.
Co je důležité
- Rozdělení procesů odstraňuje single point of failure v UI vlákně.
- gRPC streamování + Rx.NET dává reaktivní UI bez pollingu.
- IPC (Named Pipes/UDS) zajišťuje bezpečnost bez portů.
- Client-first UX skrývá složitost před uživatelem.
- Vhodné pro 24/7 aplikace se systémovým řízením.
— Editorial Team
Zatím žádné komentáře.