Skip to content

Instantly share code, notes, and snippets.

@restlessmedia
Created May 11, 2016 10:39
Show Gist options
  • Save restlessmedia/3966918fc26b00b9560aaeb055d265b3 to your computer and use it in GitHub Desktop.
Save restlessmedia/3966918fc26b00b9560aaeb055d265b3 to your computer and use it in GitHub Desktop.
public abstract class AsyncTraceListener : TraceListener
{
public AsyncTraceListener()
{
_loggingThread = new Thread(new ThreadStart(ProcessQueue))
{
// this is performed from a bg thread, to ensure the queue is serviced from a single thread
IsBackground = true
};
_loggingThread.Start();
}
public override void Write(string message)
{
lock (_queue)
{
_queue.Enqueue(() => AsyncWrite(message));
}
_hasNewItems.Set();
}
public override void WriteLine(string message)
{
lock (_queue)
{
_queue.Enqueue(() => AsyncWriteLine(message));
}
_hasNewItems.Set();
}
public override void Flush()
{
_waiting.WaitOne();
}
protected override void Dispose(bool disposing)
{
_terminate.Set();
_loggingThread.Join();
}
protected abstract void AsyncWrite(string message);
protected abstract void AsyncWriteLine(string message);
private void ProcessQueue()
{
while (true)
{
_waiting.Set();
int i = ManualResetEvent.WaitAny(new WaitHandle[] { _hasNewItems, _terminate });
// terminate was signaled
if (i == 1)
return;
_hasNewItems.Reset();
_waiting.Reset();
Queue<Action> queueCopy;
lock (_queue)
{
queueCopy = new Queue<Action>(_queue);
_queue.Clear();
}
foreach (Action fn in queueCopy)
{
fn();
}
}
}
private readonly Queue<Action> _queue = new Queue<Action>();
private readonly ManualResetEvent _hasNewItems = new ManualResetEvent(false);
private readonly ManualResetEvent _terminate = new ManualResetEvent(false);
private readonly ManualResetEvent _waiting = new ManualResetEvent(false);
private readonly Thread _loggingThread;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment