C#多线程使用读写锁ReaderWriterLockSlim同步写入文件-C/S开发框架

复杂多线程环境下使用读写锁同步写入文件
代码一:
class Program
{
static int LogCount = 1000;
static int SumLogCount = 0;
static int WritedCount = 0;
static int FailedCount = 0;
static void Main(string[] args)
{
SumLogCount += LogCount;
ThreadPool.QueueUserWorkItem((obj) =>
{
Parallel.For(0, LogCount, e =>
{
WriteLog();
});
});
SumLogCount += LogCount;
var thread1 = new Thread(() =>
{
Parallel.For(0, LogCount, e =>
{
ThreadPool.QueueUserWorkItem((subObj) =>
{
WriteLog();
});
});
});
thread1.IsBackground = false;
thread1.Start();
SumLogCount += LogCount;
Parallel.For(0, LogCount, e =>
{
ThreadPool.QueueUserWorkItem((obj) =>
{
WriteLog();
});
});
SumLogCount += LogCount;
var thread2 = new Thread(() =>
{
Parallel.For(0, LogCount, e =>
{
WriteLog();
});
});
thread2.IsBackground = false;
thread2.Start();
SumLogCount += LogCount;
Parallel.For(0, LogCount, e =>
{
WriteLog();
});
Console.WriteLine("Main Thread Processed.\r\n");
while (true)
{
Console.WriteLine(string.Format("Sum Log Count:{0}.\t\tWrited Count:{1}.\tFailed Count:{2}.", SumLogCount.ToString(), WritedCount.ToString(), FailedCount.ToString()));
Console.ReadLine();
}
}
static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
static void WriteLog()
{
try
{
LogWriteLock.EnterWriteLock();
var logFilePath = "log.txt";
var now = DateTime.Now;
var logContent = string.Format("Tid: {0}{1} {2}.{3}\r\n", Thread.CurrentThread.ManagedThreadId.ToString().PadRight(4), now.ToLongDateString(), now.ToLongTimeString(), now.Millisecond.ToString());
File.AppendAllText(logFilePath, logContent);
WritedCount++;
}
catch (Exception)
{
FailedCount++;
}
finally
{
LogWriteLock.ExitWriteLock();
}
}
}
运行结果:
复杂多线程环境下使用读写锁,全部日志成功写入了日志文件,由ThreadId和DateTime可以看出是由不同的线程同步写入。

代码二:
class Program
{
static void Main(string[] args)
{
#region 简单使用
#endregion
#region 测试代码
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "test.log").ToUpper();
var mutexKey = MutexExample.GetFilePathMutexKey(filePath);
Parallel.For(0, LogCount, e =>
{
MutexExample.MutexExec(mutexKey, () =>
{
WriteLog(filePath);
});
});
Console.WriteLine(string.Format("Log Count:{0}.\t\tWrited Count:{1}.\tFailed Count:{2}.", LogCount.ToString(), WritedCount.ToString(), FailedCount.ToString()));
Console.Read();
#endregion
}
public static class MutexExample
{
[Obsolete(error: false, message: "请使用MutexExec")]
public static void MutexExecEasy(string mutexKey, Action action)
{
using (Mutex mut = new Mutex(false, mutexKey))
{
try
{
mut.WaitOne();
action();
}
finally
{
mut.ReleaseMutex();
}
}
}
public static string GetFilePathMutexKey(string filePath)
{
var fileKey = Convert.ToBase64String(Encoding.Default.GetBytes(string.Format(@"FILE\{0}", filePath)));
var mutexKey = string.Format(@"Global\{0}", fileKey);
return mutexKey;
}
public static void MutexExec(string mutexKey, Action action)
{
MutexExec(mutexKey: mutexKey, action: action, recursive: false);
}
private static void MutexExec(string mutexKey, Action action, bool recursive)
{
using (Mutex mut = new Mutex(initiallyOwned: false, name: mutexKey))
{
try
{
mut.WaitOne();
action();
}
catch (AbandonedMutexException ex)
{
if (recursive)
throw ex;
MutexExec(mutexKey: mutexKey, action: action, recursive: true);
}
finally
{
mut.ReleaseMutex();
}
}
}
}
#region 测试写文件的代码
static int LogCount = 500;
static int WritedCount = 0;
static int FailedCount = 0;
static void WriteLog(string logFilePath)
{
try
{
var now = DateTime.Now;
var logContent = string.Format("Tid: {0}{1} {2}.{3}\r\n", Thread.CurrentThread.ManagedThreadId.ToString().PadRight(4), now.ToLongDateString(), now.ToLongTimeString(), now.Millisecond.ToString());
File.AppendAllText(logFilePath, logContent);
WritedCount++;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
FailedCount++;
}
}
#endregion
}
运行结果:

