总结:一般俩中方式 一种是file以共享属性打开,第二种用手动添加读写锁实现
using System;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Text;
namespace FileThread
{
class MainClass
{
static void Main(string[] args) {
//并发运行写入日志记录,由于多个线程同时写入同一个文件将会导致错误
Parallel.For(0,LogCount,e => {
WriteLog0();
WriteLog1();
});
Console.WriteLine(string.Format("\r\n第一个文件 Log Count:{0}.\t\tWrited Count:{1}.\tFailed Count:{2}.",LogCount.ToString(),WritedCount0.ToString(),FailedCount0.ToString()));
Console.WriteLine(string.Format("\r\n第二个文件 Log Count:{0}.\t\tWrited Count:{1}.\tFailed Count:{2}.",LogCount.ToString(),WritedCount1.ToString(),FailedCount1.ToString()));
Console.Read();
}
static int LogCount = 2;
static int FailedCount0 = 0;
static int FailedCount1 = 0;
static int WritedCount0 = 0;
static int WritedCount1 = 0;
static string filePath0 = "/Users/zhixian/Documents/unrealFront/projects/FileThread/logtext0.txt";
static string filePath1 = "/Users/zhixian/Documents/unrealFront/projects/FileThread/logtext1.txt";
static void WriteLog0() {
try {
//Stopwatch stopwatch = new Stopwatch();
//stopwatch.Start();
//stopwatch.ElapsedMilliseconds
string logContent = string.Format("\r\n 无读写锁线程ID是{0},日期为{1}毫秒时间为{2},总写入次数{3} \r\n",Thread.CurrentThread.ManagedThreadId.ToString(),DateTime.Now.ToLongDateString() + "时间为" + DateTime.Now.ToLongTimeString(),DateTime.Now.Millisecond.ToString(),WritedCount0);
byte[] logContentByte = Encoding.UTF8.GetBytes(logContent);
FileStream fs = new FileStream(filePath0,FileMode.Append,FileAccess.Write,FileShare.ReadWrite);
fs.Write(logContentByte,0,logContentByte.Length);
fs.Dispose();
fs.Close();
WritedCount0++;
Console.WriteLine("无读写锁 写入成功总数:" + WritedCount0);
} catch(Exception ex) {
FailedCount0++;
Console.WriteLine("无读写锁 累计出错数:" + FailedCount0);
Console.WriteLine(ex.Message);
}
}
//读写锁,当资源处于写入模式时,其他线程写入需要等待本次写入结束之后才能继续写入
static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
static void WriteLog1() {
try {
//Stopwatch stopwatch = new Stopwatch();
//stopwatch.Start();
//stopwatch.ElapsedMilliseconds
//设置读写锁为写入模式独占资源,其他写入请求需要等待本次写入结束之后才能继续写入
//注意:长时间持有读线程锁或写线程锁会使其他线程发生饥饿 (starve)。 为了得到最好的性能,需要考虑重新构造应用程序以将写访问的持续时间减少到最小。
//从性能方面考虑,请求进入写入模式应该紧跟文件操作之前,在此处进入写入模式仅是为了降低代码复杂度
//因进入与退出写入模式应在同一个try finally语句块内,所以在请求进入写入模式之前不能触发异常,否则释放次数大于请求次数将会触发异常
Console.WriteLine("有读写锁 数据流格式 开始进入一个读写锁");
LogWriteLock.EnterWriteLock();
Console.WriteLine("#有读写锁 数据流格式 已经进入一个读写锁");
string logContent = string.Format("\r\n 有读写锁 数据流格式 线程ID是{0},日期为{1}毫秒时间为{2},总写入次数{3} \r\n",Thread.CurrentThread.ManagedThreadId.ToString(),DateTime.Now.ToLongDateString() + "时间为" + DateTime.Now.ToLongTimeString(),DateTime.Now.Millisecond.ToString(),WritedCount1);
byte[] logContentByte = Encoding.UTF8.GetBytes(logContent);
FileStream fs = new FileStream(filePath1,FileMode.Append,FileAccess.Write);
fs.Write(logContentByte,0,logContentByte.Length);
fs.Dispose();
fs.Close();
//下面是file格式的写文件
//var logContent = string.Format("\r\n 有读写锁 file格式 ID是{0},日期为{1}毫秒时间为{2},总写入次数{3} \r\n",Thread.CurrentThread.ManagedThreadId.ToString(),DateTime.Now.ToLongDateString() + "时间为" + DateTime.Now.ToLongTimeString(),DateTime.Now.Millisecond.ToString(),WritedCount2);
//File.AppendAllText(filePath2,logContent);
WritedCount1++;
Console.WriteLine("有读写锁 数据流格式 写入成功总数:" + WritedCount1);
} catch(Exception ex) {
FailedCount1++;
Console.WriteLine("有读写锁 数据流格式 累计出错数:" + FailedCount1);
Console.WriteLine(ex.Message);
} finally {
//退出写入模式,释放资源占用
//注意:一次请求对应一次释放
// 若释放次数大于、小于 请求次数都将会触发异常[写入锁定未经保持即被释放等]
Console.WriteLine("有读写锁 数据流格式 退出一个读写所锁");
LogWriteLock.ExitWriteLock();
}
}
}
}
运行结果
版权声明:本文为yuewei19原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。