Files
CommTester/ParentWpf/ChildSession.cs
Holger Börchers 894fbbfa5a Initial commit
2026-01-30 15:31:43 +01:00

130 lines
3.1 KiB
C#

using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO.Pipes;
using System.Text.Json;
using CommIpc;
namespace ParentWpf;
public sealed class ChildSession : NotifyBase, IAsyncDisposable
{
private readonly SemaphoreSlim _writeLock = new(1, 1);
private string _status = "Starting";
private double _progressPercent;
private string? _currentWorkId;
private bool _isConnected;
public int Id { get; }
public string PipeName { get; }
public string PipePath => CommIpc.PipeName.Describe(PipeName);
public NamedPipeServerStream Pipe { get; }
public Process Process { get; }
public CancellationTokenSource LifetimeCts { get; } = new();
public ObservableCollection<string> Logs { get; } = new();
public bool IsConnected
{
get => _isConnected;
set
{
if (SetField(ref _isConnected, value))
{
OnPropertyChanged(nameof(DisplayName));
OnPropertyChanged(nameof(StatusLine));
}
}
}
public string Status
{
get => _status;
set
{
if (SetField(ref _status, value))
{
OnPropertyChanged(nameof(DisplayName));
OnPropertyChanged(nameof(StatusLine));
}
}
}
public string DisplayName => $"Child {Id} ({(IsConnected ? "Connected" : "Disconnected")})";
public string StatusLine => $"{Status} | Work: {(_currentWorkId ?? "-")}";
public double ProgressPercent
{
get => _progressPercent;
set => SetField(ref _progressPercent, value);
}
public string? CurrentWorkId
{
get => _currentWorkId;
set
{
if (SetField(ref _currentWorkId, value))
{
OnPropertyChanged(nameof(StatusLine));
}
}
}
public ChildSession(int id, string pipeName, NamedPipeServerStream pipe, Process process)
{
Id = id;
PipeName = pipeName;
Pipe = pipe;
Process = process;
}
public async Task SendAsync(IpcFrame frame, CancellationToken cancellationToken)
{
await _writeLock.WaitAsync(cancellationToken);
try
{
await IpcProtocol.WriteFrameAsync(Pipe, frame, cancellationToken);
}
finally
{
_writeLock.Release();
}
}
public void AddLog(string line)
{
// keep it from growing without bounds during prototyping
if (Logs.Count > 2000)
{
Logs.RemoveAt(0);
}
Logs.Add(line);
}
public async ValueTask DisposeAsync()
{
try
{
LifetimeCts.Cancel();
}
catch { }
try
{
if (!Process.HasExited)
{
Process.Kill(entireProcessTree: true);
}
}
catch { }
try { Pipe.Dispose(); } catch { }
try { Process.Dispose(); } catch { }
try { LifetimeCts.Dispose(); } catch { }
try { _writeLock.Dispose(); } catch { }
await Task.CompletedTask;
}
}