using Hi.Disp; using Hi.Geom; using Microsoft.AspNetCore.SignalR; using Hi.Webapi.Hubs; using System.Collections.Concurrent; namespace Hi.Webapi.Services { /// /// Singleton Service for managing . /// public class RenderingService : IDisposable { /// /// Engine Dictionary. /// Key is sessionID. /// public ConcurrentDictionary EngineDictionary { get; } = new(); ILogger Logger { get; } IHubContext HubContext { get; } private bool disposedValue; public RenderingService(ILogger logger, IHubContext hubContext) { Logger = logger; HubContext = hubContext; } /// /// Get Or Create an DispEngine. /// public DispEngine GetOrCreateEngine(string connectionId) { return EngineDictionary.GetOrAdd(connectionId, id => { Logger.LogInformation($"Create new DispEngine,ConnectionId: {id}"); var engine = new DispEngine(); engine.BackgroundColor = new Vec3d(0.1, 0.1, 0.5); engine.BackgroundOpacity = 0.1; return engine; }); } /// /// Send image to specific client. /// public async Task SendImageToClient(string connectionId, byte[] compressedData, int originalLength, int width, int height) { try { await HubContext.Clients.Client(connectionId).SendAsync("ImageUpdate", compressedData, originalLength, width, height); } catch (Exception ex) { Logger.LogError(ex, $"Failed to send image to client: {connectionId}"); } } /// /// Remove DispEngine /// public bool RemoveEngine(string connectionId) { if (EngineDictionary.TryRemove(connectionId, out var engine)) { Logger.LogInformation($"Remove DispEngine,ConnectionId: {connectionId}"); try { engine.IsVisible = false; engine.Dispose(); } catch (Exception ex) { Logger.LogError(ex, $"清理 DispEngine 時發生錯誤,ConnectionId: {connectionId}"); } return true; } return false; } /// /// Get Active Engine 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 DispEngine Error,ConnectionId: {kvp.Key}"); } } EngineDictionary.Clear(); } disposedValue = true; } } /// public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } }