From 4b30df49e2be1444c01d6b52079c2048812904fe Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Aug 2025 18:49:43 +0800 Subject: [PATCH] tune --- Hubs/RenderingHub.cs | 90 ++++++++++++++++-------------------- Services/RenderingService.cs | 74 ++++++++++++++++++----------- 2 files changed, 87 insertions(+), 77 deletions(-) diff --git a/Hubs/RenderingHub.cs b/Hubs/RenderingHub.cs index 0503a37..3974e2d 100644 --- a/Hubs/RenderingHub.cs +++ b/Hubs/RenderingHub.cs @@ -11,15 +11,15 @@ namespace Hi.Webapi.Hubs /// public class RenderingHub : Hub { - private readonly RenderingService _renderingService; - private readonly ILogger _logger; private readonly Dictionary _lastFrameCache = []; private readonly Dictionary _sketchViewCache = []; + public RenderingService RenderingService { get; } + public ILogger Logger { get; } public RenderingHub(RenderingService renderingService, ILogger logger) { - _renderingService = renderingService; - _logger = logger; + RenderingService = renderingService; + Logger = logger; } /// @@ -28,18 +28,17 @@ namespace Hi.Webapi.Hubs public async Task InitializeCanvas(int width, int height) { var sessionId = Context.ConnectionId; - _logger.LogInformation($"InitializeCanvas called - SessionId: {sessionId}, Width: {width}, Height: {height}"); + Logger.LogInformation($"InitializeCanvas called - SessionId: {sessionId}, Width: {width}, Height: {height}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); - _logger.LogInformation($"Engine created/retrieved - SessionId: {sessionId}"); + var engine = RenderingService.GetOrCreateEngine(sessionId); + Logger.LogInformation($"Engine created/retrieved - SessionId: {sessionId}"); - // 啟動引擎(必須在設置回調之前) engine.Start(width, height); - _logger.LogInformation($"Engine started with size {width}x{height} - SessionId: {sessionId}"); + Logger.LogInformation($"Engine started with size {width}x{height} - SessionId: {sessionId}"); // 在設置回調之前,先捕獲客戶端代理 var clientProxy = Clients.Caller; - var logger = _logger; + var logger = Logger; var frameCount = 0; // 設置渲染回調 @@ -52,11 +51,8 @@ namespace Hi.Webapi.Hubs frameCount++; if (frameCount <= 5) // 只記錄前5幀 - { logger.LogInformation($"Frame {frameCount} rendered - Size: {w}x{h}, SessionId: {sessionId}"); - } - // 檢查寬度和高度是否有效 if (w <= 0 || h <= 0) { logger.LogWarning($"Invalid image size: {w}x{h} - SessionId: {sessionId}"); @@ -65,7 +61,6 @@ namespace Hi.Webapi.Hubs try { - // 在回調中同步處理圖像數據,轉換為 byte[] int wh = w * h; byte[] rgba = new byte[wh * 4]; for (int i = 0; i < wh; i++) @@ -85,11 +80,8 @@ namespace Hi.Webapi.Hubs } _lastFrameCache[sessionId] = rgba; - if (frameCount <= 5) - { logger.LogInformation($"Frame {frameCount} sending - Size: {w}x{h}, Data: {rgba.Length} bytes"); - } using MemoryStream dstMemoryStream = new MemoryStream(); using GZipStream gZipStream = new GZipStream(dstMemoryStream, CompressionMode.Compress); @@ -104,9 +96,7 @@ namespace Hi.Webapi.Hubs var compressionRatio = (float)compressedRgbaArray.Length / rgba.Length * 100; if (frameCount <= 5) - { logger.LogInformation($"Compressed: {compressedRgbaArray.Length} bytes ({compressionRatio:F1}% of original)"); - } // 發送壓縮數據到客戶端(注意:第二個參數應該是原始長度,不是壓縮後的長度) _ = clientProxy.SendAsync("ImageUpdate", @@ -144,14 +134,14 @@ namespace Hi.Webapi.Hubs engine.SetViewToHomeView(); _sketchViewCache[sessionId] = engine.SketchView; } - _logger.LogInformation($"View initialized - SessionId: {sessionId}"); + Logger.LogInformation($"View initialized - SessionId: {sessionId}"); // 確保引擎可見並開始渲染 engine.IsVisible = true; - _logger.LogInformation($"Engine visibility set to true - SessionId: {sessionId}"); + Logger.LogInformation($"Engine visibility set to true - SessionId: {sessionId}"); await Clients.Caller.SendAsync("CanvasInitialized", sessionId); - _logger.LogInformation($"Canvas initialized for session: {sessionId}"); + Logger.LogInformation($"Canvas initialized for session: {sessionId}"); } /// @@ -160,9 +150,9 @@ namespace Hi.Webapi.Hubs public Task HandleMouseMove(double x, double y, int buttonMask) { var sessionId = Context.ConnectionId; - _logger.LogDebug($"HandleMouseMove - SessionId: {sessionId}, X: {x}, Y: {y}, ButtonMask: {buttonMask}"); + Logger.LogDebug($"HandleMouseMove - SessionId: {sessionId}, X: {x}, Y: {y}, ButtonMask: {buttonMask}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); var p = new Vec2i((int)x, (int)y); // 移動鼠標 @@ -189,9 +179,9 @@ namespace Hi.Webapi.Hubs public Task HandleMouseDown(double x, double y, int button) { var sessionId = Context.ConnectionId; - _logger.LogInformation($"HandleMouseDown - SessionId: {sessionId}, X: {x}, Y: {y}, Button: {button}"); + Logger.LogInformation($"HandleMouseDown - SessionId: {sessionId}, X: {x}, Y: {y}, Button: {button}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); engine.MouseButtonDown(button); return Task.CompletedTask; } @@ -202,9 +192,9 @@ namespace Hi.Webapi.Hubs public Task HandleMouseUp(double x, double y, int button) { var sessionId = Context.ConnectionId; - _logger.LogInformation($"HandleMouseUp - SessionId: {sessionId}, X: {x}, Y: {y}, Button: {button}"); + Logger.LogInformation($"HandleMouseUp - SessionId: {sessionId}, X: {x}, Y: {y}, Button: {button}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); engine.MouseButtonUp(button); return Task.CompletedTask; } @@ -215,9 +205,9 @@ namespace Hi.Webapi.Hubs public Task HandleMouseWheel(double x, double y, double deltaX, double deltaY, string browserBrand = "chrome") { var sessionId = Context.ConnectionId; - _logger.LogInformation($"HandleMouseWheel - SessionId: {sessionId}, X: {x}, Y: {y}, DeltaX: {deltaX}, DeltaY: {deltaY}, Browser: {browserBrand}"); + Logger.LogInformation($"HandleMouseWheel - SessionId: {sessionId}, X: {x}, Y: {y}, DeltaX: {deltaX}, DeltaY: {deltaY}, Browser: {browserBrand}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); // 根據瀏覽器類型獲取縮放比例 double scale = GetWheelScaling(browserBrand); @@ -239,9 +229,9 @@ namespace Hi.Webapi.Hubs public Task HandleResize(int width, int height) { var sessionId = Context.ConnectionId; - _logger.LogInformation($"HandleResize - SessionId: {sessionId}, Width: {width}, Height: {height}"); + Logger.LogInformation($"HandleResize - SessionId: {sessionId}, Width: {width}, Height: {height}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); // 重置圖像緩存以強制重新渲染 if (_lastFrameCache.ContainsKey(sessionId)) @@ -251,7 +241,7 @@ namespace Hi.Webapi.Hubs engine.Resize(width, height); - _logger.LogInformation($"Resize completed - SessionId: {sessionId}"); + Logger.LogInformation($"Resize completed - SessionId: {sessionId}"); return Task.CompletedTask; } @@ -261,9 +251,9 @@ namespace Hi.Webapi.Hubs public Task HandleVisibilityChange(string visibilityState) { var sessionId = Context.ConnectionId; - _logger.LogInformation($"HandleVisibilityChange - SessionId: {sessionId}, State: {visibilityState}"); + Logger.LogInformation($"HandleVisibilityChange - SessionId: {sessionId}, State: {visibilityState}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); engine.IsVisible = visibilityState == "visible"; return Task.CompletedTask; @@ -275,9 +265,9 @@ namespace Hi.Webapi.Hubs public Task SetView(string viewType) { var sessionId = Context.ConnectionId; - _logger.LogInformation($"SetView called - SessionId: {sessionId}, ViewType: {viewType}"); + Logger.LogInformation($"SetView called - SessionId: {sessionId}, ViewType: {viewType}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); switch (viewType.ToLower()) { @@ -309,7 +299,7 @@ namespace Hi.Webapi.Hubs engine.SetViewToHomeView(); break; default: - _logger.LogWarning($"Unknown view type: {viewType} - SessionId: {sessionId}"); + Logger.LogWarning($"Unknown view type: {viewType} - SessionId: {sessionId}"); break; } @@ -324,9 +314,9 @@ namespace Hi.Webapi.Hubs public Task HandleKeyDown(string key, string code, bool ctrlKey, bool shiftKey, bool altKey) { var sessionId = Context.ConnectionId; - _logger.LogInformation($"HandleKeyDown - SessionId: {sessionId}, Key: {key}, Code: {code}, Ctrl: {ctrlKey}, Shift: {shiftKey}, Alt: {altKey}"); + Logger.LogInformation($"HandleKeyDown - SessionId: {sessionId}, Key: {key}, Code: {code}, Ctrl: {ctrlKey}, Shift: {shiftKey}, Alt: {altKey}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); // 使用 key 的 HashCode(與 Blazor 版本一致) long keyCode = key.ToLower().GetHashCode(); @@ -360,9 +350,9 @@ namespace Hi.Webapi.Hubs public Task HandleKeyUp(string key, string code, bool ctrlKey, bool shiftKey, bool altKey) { var sessionId = Context.ConnectionId; - _logger.LogInformation($"HandleKeyUp - SessionId: {sessionId}, Key: {key}, Code: {code}, Ctrl: {ctrlKey}, Shift: {shiftKey}, Alt: {altKey}"); + Logger.LogInformation($"HandleKeyUp - SessionId: {sessionId}, Key: {key}, Code: {code}, Ctrl: {ctrlKey}, Shift: {shiftKey}, Alt: {altKey}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); long keyCode = key.ToLower().GetHashCode(); engine.KeyUp(keyCode); @@ -376,9 +366,9 @@ namespace Hi.Webapi.Hubs public Task HandleTouchDown(int pointerId, double x, double y) { var sessionId = Context.ConnectionId; - _logger.LogInformation($"HandleTouchDown - SessionId: {sessionId}, PointerId: {pointerId}, X: {x}, Y: {y}"); + Logger.LogInformation($"HandleTouchDown - SessionId: {sessionId}, PointerId: {pointerId}, X: {x}, Y: {y}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); engine.TouchDown(pointerId, (int)x, (int)y); return Task.CompletedTask; @@ -390,9 +380,9 @@ namespace Hi.Webapi.Hubs public Task HandleTouchMove(int pointerId, double x, double y) { var sessionId = Context.ConnectionId; - _logger.LogDebug($"HandleTouchMove - SessionId: {sessionId}, PointerId: {pointerId}, X: {x}, Y: {y}"); + Logger.LogDebug($"HandleTouchMove - SessionId: {sessionId}, PointerId: {pointerId}, X: {x}, Y: {y}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); engine.TouchMove(pointerId, (int)x, (int)y); return Task.CompletedTask; @@ -404,9 +394,9 @@ namespace Hi.Webapi.Hubs public Task HandleTouchUp(int pointerId) { var sessionId = Context.ConnectionId; - _logger.LogInformation($"HandleTouchUp - SessionId: {sessionId}, PointerId: {pointerId}"); + Logger.LogInformation($"HandleTouchUp - SessionId: {sessionId}, PointerId: {pointerId}"); - var engine = _renderingService.GetOrCreateEngine(sessionId); + var engine = RenderingService.GetOrCreateEngine(sessionId); engine.TouchUp(pointerId); return Task.CompletedTask; @@ -440,8 +430,8 @@ namespace Hi.Webapi.Hubs _lastFrameCache.Remove(sessionId); _sketchViewCache.Remove(sessionId); - _renderingService.RemoveEngine(sessionId); - _logger.LogInformation($"Client disconnected: {sessionId}"); + RenderingService.RemoveEngine(sessionId); + Logger.LogInformation($"Client disconnected: {sessionId}"); await base.OnDisconnectedAsync(exception); } } diff --git a/Services/RenderingService.cs b/Services/RenderingService.cs index 9c54e0d..12d2e1e 100644 --- a/Services/RenderingService.cs +++ b/Services/RenderingService.cs @@ -6,16 +6,21 @@ using System.Collections.Concurrent; namespace Hi.Webapi.Services { /// - /// 管理 DispEngine 實例和渲染操作的服務 + /// Singleton Service for managing . /// public class RenderingService : IDisposable { - private readonly ConcurrentDictionary _engines = new(); - private readonly ILogger _logger; + /// + /// Engine Dictionary. + /// Key is sessionID. + /// + public ConcurrentDictionary EngineDictionary { get; } = new(); + ILogger Logger { get; } + private bool disposedValue; - public RenderingService(ILogger logger) + public RenderingService(ILogger logger) { - _logger = logger; + Logger = logger; } /// @@ -23,9 +28,9 @@ namespace Hi.Webapi.Services /// public DispEngine GetOrCreateEngine(string sessionId) { - return _engines.GetOrAdd(sessionId, id => + return EngineDictionary.GetOrAdd(sessionId, id => { - _logger.LogInformation($"創建新的 DispEngine,SessionId: {id}"); + Logger.LogInformation($"創建新的 DispEngine,SessionId: {id}"); var engine = new DispEngine(); engine.BackgroundColor = new Vec3d(0.1, 0.1, 0.5); engine.BackgroundOpacity = 0.1; @@ -38,9 +43,9 @@ namespace Hi.Webapi.Services /// public bool RemoveEngine(string sessionId) { - if (_engines.TryRemove(sessionId, out var engine)) + if (EngineDictionary.TryRemove(sessionId, out var engine)) { - _logger.LogInformation($"移除 DispEngine,SessionId: {sessionId}"); + Logger.LogInformation($"移除 DispEngine,SessionId: {sessionId}"); try { @@ -52,7 +57,7 @@ namespace Hi.Webapi.Services } catch (Exception ex) { - _logger.LogError(ex, $"清理 DispEngine 時發生錯誤,SessionId: {sessionId}"); + Logger.LogError(ex, $"清理 DispEngine 時發生錯誤,SessionId: {sessionId}"); } return true; @@ -63,23 +68,38 @@ namespace Hi.Webapi.Services /// /// 獲取當前活動的引擎數量 /// - public int GetActiveEngineCount() => _engines.Count; + public int GetActiveEngineCount() => EngineDictionary.Count; + /// + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + foreach (var kvp in EngineDictionary) + { + try + { + kvp.Value.IsVisible = false; + kvp.Value.Dispose(); + } + catch (Exception ex) + { + Logger.LogError(ex, $"Dispose 時清理引擎錯誤,SessionId: {kvp.Key}"); + } + } + EngineDictionary.Clear(); + } - public void Dispose() - { - foreach (var kvp in _engines) - { - try - { - kvp.Value.IsVisible = false; - kvp.Value.Dispose(); - } - catch (Exception ex) - { - _logger.LogError(ex, $"Dispose 時清理引擎錯誤,SessionId: {kvp.Key}"); - } - } - _engines.Clear(); - } + disposedValue = true; + } + } + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } } \ No newline at end of file