From e57938fbda9bff702004038f76d009422968bff5 Mon Sep 17 00:00:00 2001
From: alielie <alielie@git.com>
Date: 星期五, 06 十一月 2026 18:05:07 +0800
Subject: [PATCH] 提交代码
---
DeviceService/ServiceManager/NamePipe/NamePipeService.cs | 424 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 424 insertions(+), 0 deletions(-)
diff --git a/DeviceService/ServiceManager/NamePipe/NamePipeService.cs b/DeviceService/ServiceManager/NamePipe/NamePipeService.cs
new file mode 100644
index 0000000..5efa826
--- /dev/null
+++ b/DeviceService/ServiceManager/NamePipe/NamePipeService.cs
@@ -0,0 +1,424 @@
+锘縰sing DeviceService.Core;
+using System.IO;
+using System.IO.Pipes;
+using System.Text.Json;
+
+namespace DeviceService.Service.NamePipe
+{
+ /// <summary>
+ /// 鍩轰簬鍛藉悕绠¢亾鐨勬湇鍔$瀹炵幇锛圡essage 妯″紡锛夈��
+ /// 鍚姩鍚庢寔缁洃鍚鎴风杩炴帴锛屾敹鍒扮殑姣忔潯娑堟伅閫氳繃 <see cref="DataReceived"/> 浜嬩欢涓婃姏锛�
+ /// 骞舵惡甯﹀彲鍥炲啓鏁版嵁鐨� <see cref="NamePipeClient"/> 瀹炰緥銆�
+ /// </summary>
+ public class NamePipeService : IService, IDisposable
+ {
+ /// <summary>榛樿鍏佽鐨勬渶澶х閬撳疄渚嬫暟锛堝嵆鏈�澶у苟鍙戣繛鎺ユ暟锛夈��</summary>
+ public const int DefaultMaxInstances = 254;
+
+ /// <summary>鍋滄鏈嶅姟鏃剁瓑寰呭悗鍙颁换鍔$粨鏉熺殑鏈�闀挎椂闂淬��</summary>
+ private static readonly TimeSpan StopTimeout = TimeSpan.FromSeconds(3);
+
+ private readonly string _pipeName;
+ private readonly int _maxInstances;
+ private readonly object _sync = new object();
+ private readonly Dictionary<NamePipeClient, Task> _clients = new Dictionary<NamePipeClient, Task>();
+
+ private CancellationTokenSource? _cts;
+ private NamedPipeServerStream? _listenStream;
+ private Task? _acceptTask;
+ private bool _running;
+ private bool _disposed;
+
+ /// <param name="pipeName">绠¢亾鍚嶇О锛屼负绌烘椂鍦� Start 闃舵鏍¢獙澶辫触銆�</param>
+ /// <param name="maxInstances">鏈�澶у苟鍙戣繛鎺ユ暟銆�</param>
+ public NamePipeService(string? pipeName = null, int maxInstances = DefaultMaxInstances)
+ {
+ if (maxInstances <= 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(maxInstances), "鏈�澶у疄渚嬫暟蹇呴』澶т簬 0銆�");
+ }
+ _pipeName = pipeName ?? string.Empty;
+ _maxInstances = maxInstances;
+ }
+ public event EventHandler<IClient>? ClientConnected;
+ public event EventHandler<IClient>? ClientDisConnected;
+ public event EventHandler<RequestArg>? DataReceived;
+
+ /// <summary>绠¢亾鍚嶇О銆�</summary>
+ public string PipeName => _pipeName;
+
+ /// <summary>鏈嶅姟鏄惁澶勪簬鐩戝惉鐘舵�併��</summary>
+ public bool IsRunning
+ {
+ get
+ {
+ lock (_sync)
+ {
+ return _running;
+ }
+ }
+ }
+
+ /// <summary>褰撳墠宸茶繛鎺ョ殑瀹㈡埛绔暟閲忋��</summary>
+ public int ClientCount
+ {
+ get
+ {
+ lock (_sync)
+ {
+ return _clients.Count;
+ }
+ }
+ }
+
+ public bool Start(out string msg)
+ {
+ lock (_sync)
+ {
+ if (_disposed)
+ {
+ msg = "鏈嶅姟宸查噴鏀撅紝鏃犳硶鍚姩銆�";
+ return false;
+ }
+
+ if (_running)
+ {
+ msg = "鏈嶅姟宸插浜庤繍琛岀姸鎬併��";
+ return false;
+ }
+
+ if (string.IsNullOrWhiteSpace(_pipeName))
+ {
+ msg = "绠¢亾鍚嶇О鏈缃紝鏃犳硶鍚姩銆�";
+ return false;
+ }
+
+ NamedPipeServerStream listenStream;
+ try
+ {
+ listenStream = CreatePipeStream();
+ }
+ catch (Exception ex)
+ {
+ msg = $"鍒涘缓鍛藉悕绠¢亾 \"{_pipeName}\" 澶辫触锛歿ex.Message}";
+ return false;
+ }
+
+ var cts = new CancellationTokenSource();
+ _cts = cts;
+ _listenStream = listenStream;
+ _running = true;
+ _acceptTask = Task.Run(() => AcceptLoopAsync(listenStream, cts.Token));
+ }
+
+ msg = $"鍛藉悕绠¢亾 \"{_pipeName}\" 宸插惎鍔ㄧ洃鍚��";
+ return true;
+ }
+
+ public bool Stop(out string msg)
+ {
+ Task? acceptTask;
+ List<Task> clientTasks = new List<Task>();
+
+ lock (_sync)
+ {
+ if (!_running)
+ {
+ msg = "鏈嶅姟鏈繍琛屻��";
+ return false;
+ }
+
+ _running = false;
+ acceptTask = _acceptTask;
+ _acceptTask = null;
+
+ try
+ {
+ _cts?.Cancel();
+ }
+ catch
+ {
+ // 蹇界暐鍙栨秷杩囩▼涓殑寮傚父
+ }
+
+ try
+ {
+ _listenStream?.Dispose();
+ }
+ catch
+ {
+ // 蹇界暐鍏抽棴鐩戝惉娴佺殑寮傚父
+ }
+
+ _listenStream = null;
+
+ // 鍏抽棴鎵�鏈夊鎴风杩炴帴锛屼娇闃诲涓殑璇诲彇绔嬪嵆缁撴潫
+ foreach (KeyValuePair<NamePipeClient, Task> item in _clients)
+ {
+ try
+ {
+ item.Key.Dispose();
+ }
+ catch
+ {
+ // 蹇界暐鍗曚釜杩炴帴鐨勫叧闂紓甯�
+ }
+
+ clientTasks.Add(item.Value);
+ }
+
+ _clients.Clear();
+
+ _cts?.Dispose();
+ _cts = null;
+ }
+
+ try
+ {
+ acceptTask?.Wait(StopTimeout);
+ if (clientTasks.Count > 0)
+ {
+ Task.WaitAll(clientTasks.ToArray(), StopTimeout);
+ }
+ }
+ catch (AggregateException)
+ {
+ // 鍚庡彴浠诲姟鍦ㄦ牎楠�/鍙栨秷闃舵鎶涘嚭鐨勫紓甯告棤闇�鍚戜笂浼犳挱
+ }
+
+ msg = "鏈嶅姟宸插仠姝€��";
+ return true;
+ }
+
+ private NamedPipeServerStream CreatePipeStream()
+ {
+ var pipe = new NamedPipeServerStream(
+ _pipeName,
+ PipeDirection.InOut,
+ _maxInstances,
+ PipeTransmissionMode.Message,
+ PipeOptions.Asynchronous);
+ pipe.ReadMode = PipeTransmissionMode.Message;
+ return pipe;
+ }
+
+ /// <summary>
+ /// 杩炴帴鎺ュ彈寰幆锛氭瘡鎺ュ彈涓�涓繛鎺ュ氨浜ょ粰鐙珛鐨勫鐞嗕换鍔★紝骞跺噯澶囦笅涓�涓閬撳疄渚嬬户缁洃鍚��
+ /// </summary>
+ private async Task AcceptLoopAsync(NamedPipeServerStream initial, CancellationToken token)
+ {
+ NamedPipeServerStream? listenStream = initial;
+ try
+ {
+ while (!token.IsCancellationRequested)
+ {
+ NamedPipeServerStream stream = listenStream!;
+ listenStream = null;
+
+ try
+ {
+ await stream.WaitForConnectionAsync(token).ConfigureAwait(false);
+ }
+ catch (OperationCanceledException)
+ {
+ stream.Dispose();
+ break;
+ }
+ catch (ObjectDisposedException)
+ {
+ break;
+ }
+ catch (IOException)
+ {
+ stream.Dispose();
+ break;
+ }
+
+ // .NET Framework 涓� WaitForConnectionAsync 鍙兘鎻愬墠杩斿洖锛屾澶勬牎楠岃繛鎺ョ‘瀹炲缓绔�
+ if (!stream.IsConnected)
+ {
+ try
+ {
+ await Task.Delay(50, token).ConfigureAwait(false);
+ }
+ catch (OperationCanceledException)
+ {
+ break;
+ }
+
+ listenStream = stream;
+ continue;
+ }
+
+ var client = new NamePipeClient(stream);
+ Task handler = Task.Run(() => HandleClientAsync(client, token));
+ RegisterClient(client, handler);
+
+ // 涓轰笅涓�涓繛鎺ュ噯澶囨柊鐨勭閬撳疄渚�
+ try
+ {
+ listenStream = CreatePipeStream();
+ }
+ catch (Exception)
+ {
+ break;
+ }
+
+ lock (_sync)
+ {
+ if (!_running)
+ {
+ break;
+ }
+
+ _listenStream = listenStream;
+ }
+ }
+ }
+ catch (Exception)
+ {
+ // 鐩戝惉寰幆涓殑鏈煡寮傚父鐩存帴缁撴潫寰幆锛岀敱 Stop 璐熻矗鏀跺熬
+ }
+ finally
+ {
+ try
+ {
+ listenStream?.Dispose();
+ }
+ catch
+ {
+ // 蹇界暐鍏抽棴寮傚父
+ }
+
+ lock (_sync)
+ {
+ _listenStream = null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// 鍗曚釜杩炴帴鐨勮鍙栧惊鐜細鎸夎璇诲彇娑堟伅骞惰Е鍙� <see cref="DataReceived"/>銆�
+ /// </summary>
+ private async Task HandleClientAsync(NamePipeClient client, CancellationToken token)
+ {
+ OnClientEvent(ClientConnected, client);
+ try
+ {
+ while (!token.IsCancellationRequested)
+ {
+ string? message = await client.ReadMessageAsync().ConfigureAwait(false);
+ if (message == null)
+ {
+ break;
+ }
+
+ RaiseDataReceived(client, message);
+ }
+ }
+ catch (OperationCanceledException)
+ {
+ // 鏈嶅姟鍋滄瀵艰嚧鐨勬甯稿彇娑�
+ }
+ catch (Exception)
+ {
+ // 杩炴帴鏂紑銆佹暟鎹潪娉曠瓑鎯呭喌鐩存帴缁撴潫璇ヨ繛鎺ョ殑璇诲彇
+ }
+ finally
+ {
+ OnClientEvent(ClientDisConnected, client);
+ UnregisterClient(client);
+ client.Dispose();
+ }
+ }
+
+ private void OnClientEvent(EventHandler<IClient>? handler, IClient client)
+ {
+ if (handler == null)
+ {
+ return;
+ }
+
+ try
+ {
+ handler(this, client);
+ }
+ catch
+ {
+ // 璁㈤槄鏂圭殑寮傚父涓嶅簲褰卞搷杩炴帴鐨勫缓绔嬩笌閲婃斁
+ }
+ }
+
+ private void RaiseDataReceived(NamePipeClient client, string raw)
+ {
+ var data = JsonSerializer.Deserialize<RequestData>(raw);
+ var arg = new RequestArg
+ {
+ Data = data,
+ Raw = raw,
+ Client = client
+ };
+ OnDataReceived(arg);
+ }
+
+ private void RegisterClient(NamePipeClient client, Task handler)
+ {
+ lock (_sync)
+ {
+ if (_running)
+ {
+ _clients[client] = handler;
+ return;
+ }
+ }
+
+ // 鏈嶅姟姝e湪鍋滄锛岀洿鎺ラ噴鏀捐杩炴帴
+ client.Dispose();
+ }
+
+ private void UnregisterClient(NamePipeClient client)
+ {
+ lock (_sync)
+ {
+ _clients.Remove(client);
+ }
+ }
+
+ private void OnDataReceived(RequestArg arg)
+ {
+ EventHandler<RequestArg>? handler = DataReceived;
+ if (handler == null)
+ {
+ return;
+ }
+
+ try
+ {
+ handler?.Invoke(this, arg);
+ }
+ catch
+ {
+ // 璁㈤槄鏂圭殑寮傚父涓嶅簲涓柇绠¢亾璇诲彇
+ }
+ }
+
+ public void Dispose()
+ {
+ if (_disposed)
+ {
+ return;
+ }
+
+ try
+ {
+ Stop(out _);
+ }
+ catch
+ {
+ // 閲婃斁闃舵鐨勫紓甯稿拷鐣�
+ }
+
+ _disposed = true;
+ }
+ }
+}
--
Gitblit v1.9.1