Instead of creating a thread queue, why not create a message queue that will be written? So you could have a unique thread that wrote the messages and avoided the access problem, thus creating a producer/consumer system.
The steps, roughly speaking, would be:
- Place log write code inside an action;
- Put that action in a
blocking collection
;
- Have a
thread
dedicated to the logging that consumes the blocking collection
and perform the actions received, thus ensuring the sequential writing of logs in the file;
An implementation based on the points above:
var LogCollection = new BlockingCollection<Action>();
public static void LogMessage(string messageToLog)
{
LogCollection.Add(() => File.WriteAllText("", messageToLog));
}
public static void WriteLogMessages(CancellationToken token)
{
foreach (var msg in LogCollection.GetConsumingEnumerable(token))
{
msg();
}
}
Using would look like this:
public static void Main()
{
using (CancellationTokenSource cts = new CancellationTokenSource())
{
Thread t1 = new Thread(() => WriteLogMessages(cts.Token));
t1.Start();
LogMessage("Hello World");
Console.ReadKey();
cts.Cancel();
t1.Join();
}
}
Note:
For more ideas, and if you’ve decided to use your own log implementation, take a look at the Nlog for more inspiration.