feat: Implement Debug Console Server for enhanced logging and remote monitoring
This commit is contained in:
parent
749f0f7eff
commit
10a1617833
|
@ -534,7 +534,7 @@ namespace CtrEditor.HydraulicSimulator
|
||||||
/*
|
/*
|
||||||
if (VerboseOutput)
|
if (VerboseOutput)
|
||||||
{
|
{
|
||||||
Debug.WriteLine($"Bomba {pump.GetType().Name}: Velocidad={pump.SpeedRatio:F2}, " +
|
Trace.WriteLine($"Bomba {pump.GetType().Name}: Velocidad={pump.SpeedRatio:F2}, " +
|
||||||
$"Funcionando={pump.IsRunning}, Dirección={pump.PumpDirection}");
|
$"Funcionando={pump.IsRunning}, Dirección={pump.PumpDirection}");
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -567,17 +567,18 @@ namespace CtrEditor.HydraulicSimulator
|
||||||
// Calcular presión basada en nivel si no es presión fija
|
// Calcular presión basada en nivel si no es presión fija
|
||||||
if (!tank.IsFixedPressure)
|
if (!tank.IsFixedPressure)
|
||||||
{
|
{
|
||||||
// P = ρgh + P_atmosferica
|
// P = ρgh + P_atmosferica (resultado en Pa)
|
||||||
double pressureFromLevel = SimulationFluid.Rho * 9.80665 * tank.Level; // + presión atmosférica
|
double pressureFromLevel = SimulationFluid.Rho * 9.80665 * tank.Level; // + presión atmosférica
|
||||||
tank.TankPressure = pressureFromLevel;
|
// Convertir de Pa a bar (1 bar = 100000 Pa)
|
||||||
|
tank.TankPressure = pressureFromLevel / 100000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug output deshabilitado para mejorar rendimiento
|
// Debug output deshabilitado para mejorar rendimiento
|
||||||
/*
|
/*
|
||||||
if (VerboseOutput)
|
if (VerboseOutput)
|
||||||
{
|
{
|
||||||
Debug.WriteLine($"Tanque {tank.GetType().Name}: Nivel={tank.Level:F2}m, " +
|
Trace.WriteLine($"Tanque {tank.GetType().Name}: Nivel={tank.Level:F2}m, " +
|
||||||
$"Presión={tank.TankPressure:F0}Pa, PresionFija={tank.IsFixedPressure}");
|
$"Presión={tank.TankPressure:F3}bar ({tank.TankPressure * 100000.0:F0}Pa), PresionFija={tank.IsFixedPressure}");
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,9 +111,9 @@ namespace CtrEditor.HydraulicSimulator
|
||||||
if (WpfObject is osHydTank tank)
|
if (WpfObject is osHydTank tank)
|
||||||
{
|
{
|
||||||
TankPressure = tank.TankPressure;
|
TankPressure = tank.TankPressure;
|
||||||
CurrentLevel = tank.CurrentLevel;
|
CurrentLevel = tank.CurrentLevelM;
|
||||||
MaxLevel = tank.MaxLevel;
|
MaxLevel = tank.MaxLevelM;
|
||||||
MinLevel = tank.MinLevel;
|
MinLevel = tank.MinLevelM;
|
||||||
CrossSectionalArea = tank.CrossSectionalArea;
|
CrossSectionalArea = tank.CrossSectionalArea;
|
||||||
IsFixedPressure = tank.IsFixedPressure;
|
IsFixedPressure = tank.IsFixedPressure;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ using System.Timers; // Para el nuevo timer de simulación más preciso
|
||||||
using CtrEditor.PopUps;
|
using CtrEditor.PopUps;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using CtrEditor.Services; // Para MCPServer y DebugConsoleServer
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using CtrEditor.Serialization; // Add this line
|
using CtrEditor.Serialization; // Add this line
|
||||||
|
@ -75,6 +76,9 @@ namespace CtrEditor
|
||||||
// Servidor MCP para control remoto
|
// Servidor MCP para control remoto
|
||||||
private MCPServer _mcpServer;
|
private MCPServer _mcpServer;
|
||||||
|
|
||||||
|
// Servidor de debug console para logging
|
||||||
|
private DebugConsoleServer _debugConsoleServer;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private int mcpServerPort = 5006;
|
private int mcpServerPort = 5006;
|
||||||
|
|
||||||
|
@ -1787,6 +1791,9 @@ namespace CtrEditor
|
||||||
await _mcpServer.StartAsync();
|
await _mcpServer.StartAsync();
|
||||||
|
|
||||||
Debug.WriteLine($"[MCP] Servidor MCP iniciado en puerto {McpServerPort}");
|
Debug.WriteLine($"[MCP] Servidor MCP iniciado en puerto {McpServerPort}");
|
||||||
|
|
||||||
|
// Iniciar también el servidor de debug console
|
||||||
|
StartDebugConsoleServer();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -1803,8 +1810,10 @@ namespace CtrEditor
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_mcpServer?.Stop();
|
_mcpServer?.Stop();
|
||||||
|
|
||||||
Debug.WriteLine("[MCP] Servidor MCP detenido");
|
Debug.WriteLine("[MCP] Servidor MCP detenido");
|
||||||
|
|
||||||
|
// Detener también el servidor de debug console
|
||||||
|
StopDebugConsoleServer();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -1821,6 +1830,9 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
_mcpServer?.Dispose();
|
_mcpServer?.Dispose();
|
||||||
_mcpServer = null;
|
_mcpServer = null;
|
||||||
|
|
||||||
|
// Limpiar también el servidor de debug console
|
||||||
|
CleanupDebugConsoleServer();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -1828,6 +1840,61 @@ namespace CtrEditor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inicia el servidor de debug console
|
||||||
|
/// </summary>
|
||||||
|
private void StartDebugConsoleServer()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_debugConsoleServer != null)
|
||||||
|
{
|
||||||
|
_debugConsoleServer.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
_debugConsoleServer = new DebugConsoleServer(5007); // Puerto fijo para debug
|
||||||
|
_debugConsoleServer.Start();
|
||||||
|
|
||||||
|
Debug.WriteLine("[Debug Console] Servidor de debug console iniciado en puerto 5007");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"[Debug Console] Error iniciando servidor de debug console: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Detiene el servidor de debug console
|
||||||
|
/// </summary>
|
||||||
|
private void StopDebugConsoleServer()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_debugConsoleServer?.Stop();
|
||||||
|
Debug.WriteLine("[Debug Console] Servidor de debug console detenido");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"[Debug Console] Error deteniendo servidor de debug console: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Limpia el servidor de debug console al cerrar la aplicación
|
||||||
|
/// </summary>
|
||||||
|
private void CleanupDebugConsoleServer()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_debugConsoleServer?.Dispose();
|
||||||
|
_debugConsoleServer = null;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"[Debug Console] Error limpiando servidor de debug console: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -634,10 +634,10 @@ namespace CtrEditor.ObjetosSim
|
||||||
// El tanque siempre es un nodo de presión fija si está configurado así
|
// El tanque siempre es un nodo de presión fija si está configurado así
|
||||||
if (IsFixedPressure)
|
if (IsFixedPressure)
|
||||||
{
|
{
|
||||||
// Convertir bar a Pa para el sistema hidráulico interno
|
// TankPressure ya está en Pa, no necesita conversión
|
||||||
var pressurePa = TankPressure * 100000.0;
|
var pressurePa = TankPressure;
|
||||||
nodes.Add(new HydraulicNodeDefinition(Nombre, true, pressurePa, GetTankDescription()));
|
nodes.Add(new HydraulicNodeDefinition(Nombre, true, pressurePa, GetTankDescription()));
|
||||||
//Debug.WriteLine($"Tanque {Nombre}: Nodo de presión fija creado - {TankPressure:F2} bar ({pressurePa:F0} Pa)");
|
//Debug.WriteLine($"Tanque {Nombre}: Nodo de presión fija creado - {TankPressure:F0} Pa ({TankPressure/100000.0:F2} bar)");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -655,10 +655,10 @@ namespace CtrEditor.ObjetosSim
|
||||||
// Obtener flujos conectados
|
// Obtener flujos conectados
|
||||||
UpdateFlowsFromConnectedPipes(flows);
|
UpdateFlowsFromConnectedPipes(flows);
|
||||||
|
|
||||||
// Actualizar presión (convertir de Pa a bar)
|
// Actualizar presión (convertir de Pa a bar para consistencia)
|
||||||
if (pressures.ContainsKey(Nombre))
|
if (pressures.ContainsKey(Nombre))
|
||||||
{
|
{
|
||||||
CurrentPressure = pressures[Nombre] / 100000.0; // Pa a bar
|
CurrentPressure = pressures[Nombre] / 100000.0; // Convertir Pa a bar
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualizar nivel basado en balance de flujo
|
// Actualizar nivel basado en balance de flujo
|
||||||
|
@ -666,9 +666,9 @@ namespace CtrEditor.ObjetosSim
|
||||||
|
|
||||||
if (VerboseLogging())
|
if (VerboseLogging())
|
||||||
{
|
{
|
||||||
Debug.WriteLine($"Tanque {Nombre}: Nivel={CurrentLevelM:F2}m ({FillPercentage:F1}%), " +
|
Trace.WriteLine($"Tanque {Nombre}: Nivel={CurrentLevelM:F2}m ({FillPercentage:F1}%), " +
|
||||||
$"Flujo_entrada={InletFlow:F2}L/min, Flujo_salida={OutletFlow:F2}L/min, " +
|
$"Flujo_entrada={InletFlow:F2}L/min, Flujo_salida={OutletFlow:F2}L/min, " +
|
||||||
$"Balance={FlowBalance:F2}L/min, Presión={CurrentPressure:F2}bar, Fluido={CurrentFluidDescription}");
|
$"Balance={FlowBalance:F2}L/min, Presión={CurrentPressure:F3}bar ({CurrentPressure * 100000.0:F0}Pa), Fluido={CurrentFluidDescription}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1013,7 +1013,7 @@ namespace CtrEditor.ObjetosSim
|
||||||
// Debug para verificar cambios
|
// Debug para verificar cambios
|
||||||
if (VerboseLogging() && Math.Abs(volumeChangeL) > 0.1)
|
if (VerboseLogging() && Math.Abs(volumeChangeL) > 0.1)
|
||||||
{
|
{
|
||||||
Debug.WriteLine($"Tanque {Nombre}: Δt={deltaTime:F3}min, ΔVolumen={volumeChangeL:F2}L, " +
|
Trace.WriteLine($"Tanque {Nombre}: Δt={deltaTime:F3}min, ΔVolumen={volumeChangeL:F2}L, " +
|
||||||
$"Volumen={CurrentVolumeL:F1}L, Estado={MixingState}, Fluido={CurrentFluidDescription}");
|
$"Volumen={CurrentVolumeL:F1}L, Estado={MixingState}, Fluido={CurrentFluidDescription}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,281 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CtrEditor.Services
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Servidor TCP que captura y retransmite mensajes de debug console
|
||||||
|
/// Permite al MCP Proxy escuchar los logs de debug de CtrEditor
|
||||||
|
/// </summary>
|
||||||
|
public class DebugConsoleServer : IDisposable
|
||||||
|
{
|
||||||
|
private readonly int _port;
|
||||||
|
private TcpListener _tcpListener;
|
||||||
|
private bool _isRunning;
|
||||||
|
private CancellationTokenSource _cancellationTokenSource;
|
||||||
|
private readonly object _lockObject = new object();
|
||||||
|
private readonly ConcurrentQueue<string> _messageQueue = new ConcurrentQueue<string>();
|
||||||
|
private readonly ConcurrentBag<TcpClient> _connectedClients = new ConcurrentBag<TcpClient>();
|
||||||
|
|
||||||
|
// Custom TraceListener para capturar Debug.WriteLine
|
||||||
|
private DebugTraceListener _traceListener;
|
||||||
|
|
||||||
|
public DebugConsoleServer(int port = 5007)
|
||||||
|
{
|
||||||
|
_port = port;
|
||||||
|
_cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inicia el servidor de debug console
|
||||||
|
/// </summary>
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
if (_isRunning) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_tcpListener = new TcpListener(IPAddress.Loopback, _port);
|
||||||
|
_tcpListener.Start();
|
||||||
|
_isRunning = true;
|
||||||
|
|
||||||
|
// Instalar el trace listener personalizado solo para Trace
|
||||||
|
_traceListener = new DebugTraceListener(this);
|
||||||
|
Trace.Listeners.Add(_traceListener);
|
||||||
|
|
||||||
|
Trace.WriteLine($"[Debug Console Server] Servidor de debug iniciado en puerto {_port}");
|
||||||
|
|
||||||
|
// Procesar conexiones en background
|
||||||
|
_ = Task.Run(async () => await AcceptConnectionsAsync(_cancellationTokenSource.Token));
|
||||||
|
|
||||||
|
// Procesar cola de mensajes
|
||||||
|
_ = Task.Run(async () => await ProcessMessageQueueAsync(_cancellationTokenSource.Token));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"[Debug Console Server] Error al iniciar servidor: {ex.Message}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Detiene el servidor de debug console
|
||||||
|
/// </summary>
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
if (!_isRunning) return;
|
||||||
|
|
||||||
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
if (!_isRunning) return;
|
||||||
|
|
||||||
|
_isRunning = false;
|
||||||
|
_cancellationTokenSource?.Cancel();
|
||||||
|
|
||||||
|
// Remover el trace listener
|
||||||
|
if (_traceListener != null)
|
||||||
|
{
|
||||||
|
Trace.Listeners.Remove(_traceListener);
|
||||||
|
_traceListener = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tcpListener?.Stop();
|
||||||
|
|
||||||
|
// Cerrar todas las conexiones de clientes
|
||||||
|
foreach (var client in _connectedClients)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client?.Close();
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.WriteLine("[Debug Console Server] Servidor de debug detenido");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Acepta conexiones de clientes
|
||||||
|
/// </summary>
|
||||||
|
private async Task AcceptConnectionsAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (_isRunning && !cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("[Debug Console Server] Esperando conexión de cliente...");
|
||||||
|
var tcpClient = await _tcpListener.AcceptTcpClientAsync();
|
||||||
|
_connectedClients.Add(tcpClient);
|
||||||
|
|
||||||
|
Debug.WriteLine("[Debug Console Server] Cliente debug conectado");
|
||||||
|
|
||||||
|
// Manejar cliente en background
|
||||||
|
_ = Task.Run(async () => await HandleClientAsync(tcpClient, cancellationToken));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (_isRunning)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"[Debug Console Server] Error aceptando conexión: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maneja un cliente conectado
|
||||||
|
/// </summary>
|
||||||
|
private async Task HandleClientAsync(TcpClient client, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var stream = client.GetStream();
|
||||||
|
|
||||||
|
// Enviar mensaje de bienvenida
|
||||||
|
var welcomeMessage = $"[Debug Console Server] Conectado al servidor de debug de CtrEditor en puerto {_port}\n";
|
||||||
|
await SendMessageToClientAsync(stream, welcomeMessage);
|
||||||
|
|
||||||
|
// Mantener conexión viva hasta cancelación
|
||||||
|
while (_isRunning && client.Connected && !cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
await Task.Delay(1000, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"[Debug Console Server] Error en cliente debug: {ex.Message}");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client?.Close();
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
Debug.WriteLine("[Debug Console Server] Cliente debug desconectado");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Procesa la cola de mensajes y los envía a todos los clientes conectados
|
||||||
|
/// </summary>
|
||||||
|
private async Task ProcessMessageQueueAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (_isRunning && !cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
if (_messageQueue.TryDequeue(out string message))
|
||||||
|
{
|
||||||
|
await BroadcastMessageAsync(message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Task.Delay(50, cancellationToken); // Pequeña pausa si no hay mensajes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (_isRunning)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"[Debug Console Server] Error procesando cola de mensajes: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Envía un mensaje a todos los clientes conectados
|
||||||
|
/// </summary>
|
||||||
|
private async Task BroadcastMessageAsync(string message)
|
||||||
|
{
|
||||||
|
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
|
var formattedMessage = $"[{timestamp}] {message}\n";
|
||||||
|
|
||||||
|
var clientsToRemove = new List<TcpClient>();
|
||||||
|
|
||||||
|
foreach (var client in _connectedClients)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (client.Connected)
|
||||||
|
{
|
||||||
|
var stream = client.GetStream();
|
||||||
|
await SendMessageToClientAsync(stream, formattedMessage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clientsToRemove.Add(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
clientsToRemove.Add(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remover clientes desconectados
|
||||||
|
// Nota: ConcurrentBag no permite eliminación directa, pero no es crítico
|
||||||
|
// Los clientes desconectados se manejan en HandleClientAsync
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Envía un mensaje a un cliente específico
|
||||||
|
/// </summary>
|
||||||
|
private async Task SendMessageToClientAsync(NetworkStream stream, string message)
|
||||||
|
{
|
||||||
|
var data = Encoding.UTF8.GetBytes(message);
|
||||||
|
await stream.WriteAsync(data, 0, data.Length);
|
||||||
|
await stream.FlushAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Agrega un mensaje a la cola para transmisión
|
||||||
|
/// </summary>
|
||||||
|
public void QueueMessage(string message)
|
||||||
|
{
|
||||||
|
if (_isRunning)
|
||||||
|
{
|
||||||
|
_messageQueue.Enqueue(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
_cancellationTokenSource?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TraceListener personalizado que captura mensajes de Debug.WriteLine
|
||||||
|
/// y los envía al servidor de debug console
|
||||||
|
/// </summary>
|
||||||
|
internal class DebugTraceListener : TraceListener
|
||||||
|
{
|
||||||
|
private readonly DebugConsoleServer _server;
|
||||||
|
|
||||||
|
public DebugTraceListener(DebugConsoleServer server)
|
||||||
|
{
|
||||||
|
_server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(string message)
|
||||||
|
{
|
||||||
|
_server?.QueueMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteLine(string message)
|
||||||
|
{
|
||||||
|
_server?.QueueMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue