If you don't want to restructure your code dramatically like I suggested in my other answer, you could try this, which assumes your LogManager
class has:
- a static thread-safe queue,
_SynchronizedQueue
- a static object to lock on when writing,
_WriteLock
and these methods:
public static void Log(string message) {
LogManager._SynchronizedQueue.Enqueue(message);
ThreadPool.QueueUserWorkItem(LogManager.Write(null));
}
// QueueUserWorkItem accepts a WaitCallback that requires an object parameter
private static void Write(object data) {
// This ensures only one thread can write at a time, but it's dangerous
lock(LogManager._WriteLock) {
string message = (string)LogManager._SynchronizedQueue.Dequeue();
if (message != null) {
// Your file writing logic here
}
}
}
There's only one problem: the lock statement in the Write
method above will guarantee only one thread can write at a time, but this is dangerous. A lot can go wrong when trying to write to a file, and you don't want to hold onto (block) thread pool threads indefinitely. Therefore, you need to use a synchronization object that lets you specify a timeout, such as a Monitor
, and rewrite your Write
method like this:
private static void Write() {
if (!Monitor.TryEnter(LogManager._WriteLock, 2000)) {
// Do whatever you want when you can't get a lock in time
} else {
try {
string message = (string)LogManager._SynchronizedQueue.Dequeue();
if (message != null) {
// Your file writing logic here
}
}
finally {
Monitor.Exit(LogManager._WriteLock);
}
}
}