|
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Threading; |
|
using System.Threading.Tasks; |
|
using WriteToFileMultiThreaded; |
|
|
|
namespace WriteToFileMultiThreaded |
|
{ |
|
using System; |
|
using System.Collections.Generic; |
|
using System.Configuration; |
|
using System.IO; |
|
|
|
|
|
/// <summary> |
|
/// A Logging class implementing the Singleton pattern and an internal Queue to be flushed perdiodically |
|
/// </summary> |
|
public class LogWriter |
|
{ |
|
private static LogWriter instance; |
|
private static Queue<Log> logQueue; |
|
private static string logDir = ""; |
|
private static string logFile = "WorkflowLog.txt"; |
|
private static int maxLogAge = int.Parse("5184000"); |
|
private static int queueSize = int.Parse("20"); |
|
private static DateTime LastFlushed = DateTime.Now; |
|
|
|
/// <summary> |
|
/// Private constructor to prevent instance creation |
|
/// </summary> |
|
private LogWriter() { } |
|
|
|
/// <summary> |
|
/// An LogWriter instance that exposes a single instance |
|
/// </summary> |
|
public static LogWriter Instance |
|
{ |
|
get |
|
{ |
|
// If the instance is null then create one and init the Queue |
|
if (instance == null) |
|
{ |
|
instance = new LogWriter(); |
|
logQueue = new Queue<Log>(); |
|
} |
|
return instance; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// The single instance method that writes to the log file |
|
/// </summary> |
|
/// <param name="message">The message to write to the log</param> |
|
public void WriteToLog(string message) |
|
{ |
|
// Lock the queue while writing to prevent contention for the log file |
|
lock (logQueue) |
|
{ |
|
// Create the entry and push to the Queue |
|
Log logEntry = new Log(message); |
|
logQueue.Enqueue(logEntry); |
|
|
|
// If we have reached the Queue Size then flush the Queue |
|
if (logQueue.Count >= queueSize || DoPeriodicFlush()) |
|
{ |
|
FlushLog(); |
|
} |
|
} |
|
} |
|
|
|
private bool DoPeriodicFlush() |
|
{ |
|
TimeSpan logAge = DateTime.Now - LastFlushed; |
|
if (logAge.TotalSeconds >= maxLogAge) |
|
{ |
|
LastFlushed = DateTime.Now; |
|
return true; |
|
} |
|
else |
|
{ |
|
return false; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Flushes the Queue to the physical log file |
|
/// </summary> |
|
private void FlushLog() |
|
{ |
|
while (logQueue.Count > 0) |
|
{ |
|
Log entry = logQueue.Dequeue(); |
|
string logPath = logDir + entry.LogDate + "_" + logFile; |
|
|
|
// This could be optimised to prevent opening and closing the file for each write |
|
using (FileStream fs = File.Open(logPath, FileMode.Append, FileAccess.Write)) |
|
{ |
|
using (StreamWriter log = new StreamWriter(fs)) |
|
{ |
|
log.WriteLine(string.Format("{0}\t{1}", entry.LogTime, entry.Message)); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// A Log class to store the message and the Date and Time the log entry was created |
|
/// </summary> |
|
public class Log |
|
{ |
|
public string Message { get; set; } |
|
public string LogTime { get; set; } |
|
public string LogDate { get; set; } |
|
|
|
public Log(string message) |
|
{ |
|
Message = message; |
|
LogDate = DateTime.Now.ToString("yyyy-MM-dd"); |
|
LogTime = DateTime.Now.ToString("hh:mm:ss.fff tt"); |
|
} |
|
} |
|
|
|
|
|
class Program |
|
{ |
|
static void Main(string[] args) |
|
{ |
|
|
|
|
|
for (int i = 0; i < 20; i++) |
|
{ |
|
string threadName = "Thread " + Convert.ToString(i + 1); |
|
Thread t = new Thread(() => ThreadData(threadName)); |
|
|
|
t.Start(); |
|
|
|
} |
|
} |
|
static void ThreadData(string threadName) |
|
{ |
|
|
|
LogWriter writer = LogWriter.Instance; |
|
for (int i = 0; i < 1000; i++) |
|
{ |
|
|
|
writer.WriteToLog(threadName + " Writing" + Environment.NewLine); |
|
//System.IO.File.AppendAllText("test.txt", "Thread One Writing Line " + i + Environment.NewLine); |
|
} |
|
} |
|
static void ThreadTwo() |
|
{ |
|
LogWriter writer = LogWriter.Instance; |
|
for (int i = 0; i < 1000; i++) |
|
{ |
|
writer.WriteToLog("Thread Two Writing Line " + i + Environment.NewLine); |
|
//System.IO.File.AppendAllText("test.txt", "Thread Two Writing Line " + i); |
|
} |
|
} |
|
} |
|
} |