Я на самом деле написал компонент tracelistener, который регистрируется в сетевом потоке. Код для этого здесь:Как вы правильно распоряжаетесь tracelistener?
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace System.Diagnostics
{
public class NetworkStreamWriterTraceListener : DelimitedListTraceListener
{
NetworkStream _stream;
StreamWriter _writer;
StreamReader _reader;
TcpClient client;
bool IsDisposed = false;
private NetworkStream GetStream(string configJson)
{
JObject config = JObject.Parse(configJson);
if (config["port"] == null)
{
throw new Configuration.ConfigurationErrorsException("port missing from json configuration");
}
client = new TcpClient();
int port = config["port"].Value<int>();
client.Connect("localhost", port);
return client.GetStream();
}
public NetworkStreamWriterTraceListener(string configJson): base(TextWriter.Null)
{
Initialize(configJson);
}
public NetworkStreamWriterTraceListener(string configJson, string name) : base(TextWriter.Null, name)
{
Initialize(configJson);
}
private void Initialize(string configJson)
{
_stream = GetStream(configJson);
_writer = new StreamWriter(_stream);
_reader = new StreamReader(_stream);
Writer = _writer;
_reader.ReadLine();
//TODO: parse response code
SendCommand("IDTY", configJson);
_reader.ReadLine();
//TODO: parse response code
AppDomain.CurrentDomain.ProcessExit += (s, e) =>
{
SendCommand("QUIT", "closing connection");
};
AppDomain.CurrentDomain.DomainUnload += (s, e) =>
{
SendCommand("QUIT", "closing connection");
};
}
public void SendCommand(string Command, string Data)
{
this.Writer.WriteLine("{0} {1}", Command, Data);
this.Writer.Flush();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
IsDisposed = true;
}
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
{
Write("LMSG ");
base.TraceEvent(eventCache, source, eventType, id, message);
Flush();
}
public override void Close()
{
base.Close();
}
}
}
Теперь я импортировал и использовал этот компонент tracelistener, успешно добавив его через конфигурацию.
Существует проблема с тем, как этот компонент предназначен для использования. До своего «расположенного» (т. Е. В общем смысле, а не в смысле сети .net) его предполагается отправить сообщение вниз по течению, сигнализирующее о завершении процесса нисходящего потока, чтобы нисходящий процесс мог освободить связанное соединение сокета.
Я попытался переопределить метод Dispose, но кажется, что метод никогда не будет вызван каркасом. Пытался написать подпрограмму деструкторов, но всякий раз, когда я пытаюсь очистить поток записи, он сгенерирует ObjectDisposedException
~NetworkStreamWriterTraceListener()
{
if(client.Connected)
{
Send("QUIT", "done with operation");
client.Close();
}
}
Я также попытался закреплять в AppDomain событий. Они тоже не работали.
Глядя на 'TextWriterTraceListener' [ссылка источника] (http://referencesource.microsoft.com/#System/compmod/system/diagnostics/TextWriterTraceListener.cs,7fdde189840b2aa2), выглядит как логика очистки является размещенных в методах 'Закрыть' и' Dispose', но я понятия не имею, вызваны они или нет. –
Слушатели размещены * TraceSource *. Не ясно, как вы трассируете, хрустальный шар говорит, что вы хотите позвонить Trace.Close() при завершении программы. –