分享

C#多线程写日志

 kittywei 2015-06-17

由于程序是3层架构的,所有多线程记录日志成了比较棘手的问题,以前还真就没有在意过写日志的问题,认为不过是写文件罢了~~!如今发现原来要实现文件共享,并且能够使多线程同时操作日志还不能相互冲突,真的很麻烦。当然要实现它我首先想到的是在网上搜,结果可能是我搜的不得其法,没发现结果,多数都是用lock,mutx等线程锁或互斥的方式写日志,偶想这样和单线程有啥区别吗?还是没能起到多线程应该有的效率!


后来问朋友,发现个log4net的东西,不过此物依然用到了线程互斥,看了源码发现的!


网络不行,朋友不知道,只好自己想办法。想了几种方法如下:


1、写多个文件,然后找个机会把这些文件合并!


2、干脆放弃写文件,改写数据库!


3、把文件看成一个表结构,实现行级锁。也就是一个线程写一行。


4、把文件看成内存块,每块写完再合并!


以上几种方法缺点:


1、多个文件。。。想起来就恶心!


2、写数据库?太没技术含量咱不干!


3、行级锁?我一个线程要写入多行不是看起来很乱?


4、没想到啥缺点,实现它吧!


以下是偶经过了10000线程并发测试,也没发现问题的代码!


 





  1. using System;  

  2. using System.Collections.Generic;  

  3. using System.Text;  

  4. namespace MTW  

  5. {  

  6.     public class MTWFile  

  7.     {  

  8.         private string _fileName;  

  9.         private static Dictionary<long, long> lockDic = new Dictionary<long, long>();  

  10.         /// <summary>  

  11.         /// 获取或设置文件名称  

  12.         /// </summary>  

  13.         public string FileName  

  14.         {  

  15.             get { return _fileName; }  

  16.             set { _fileName = value; }  

  17.         }  

  18.         /// <summary>  

  19.         /// 构造函数  

  20.         /// </summary>  

  21.         /// <param name="byteCount">每次开辟位数大小,这个直接影响到记录文件的效率</param>  

  22.         /// <param name="fileName">文件全路径名</param>  

  23.         public MTWFile(string fileName)  

  24.         {  

  25.             _fileName = fileName;  

  26.         }  

  27.         /// <summary>  

  28.         /// 创建文件  

  29.         /// </summary>  

  30.         /// <param name="fileName"></param>  

  31.         public void Create(string fileName)  

  32.         {  

  33.             if (!System.IO.File.Exists(fileName))  

  34.             {  

  35.                 using (System.IO.FileStream fs = System.IO.File.Create(fileName))  

  36.                 {  

  37.                     fs.Close();  

  38.                 }  

  39.             }  

  40.         }  

  41.         /// <summary>  

  42.         /// 写入文本  

  43.         /// </summary>  

  44.         /// <param name="content">文本内容</param>  

  45.         private void Write(string content, string newLine)  

  46.         {  

  47.             if (string.IsNullOrEmpty(_fileName))  

  48.             {  

  49.                 throw new Exception("FileName不能为空!");  

  50.             }  

  51.             using (System.IO.FileStream fs = new System.IO.FileStream(_fileName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, System.IO.FileShare.ReadWrite, 8, System.IO.FileOptions.Asynchronous))  

  52.             {  

  53.                 //Byte[] dataArray = System.Text.Encoding.ASCII.GetBytes(System.DateTime.Now.ToString() + content + "/r/n");  

  54.                 Byte[] dataArray = System.Text.Encoding.Default.GetBytes(content + newLine);  

  55.                 bool flag = true;  

  56.                 long slen = dataArray.Length;  

  57.                 long len = 0;  

  58.                 while (flag)  

  59.                 {  

  60.                     try  

  61.                     {  

  62.                         if (len >= fs.Length)  

  63.                         {  

  64.                             fs.Lock(len, slen);  

  65.                             lockDic[len] = slen;  

  66.                             flag = false;  

  67.                         }  

  68.                         else  

  69.                         {  

  70.                             len = fs.Length;  

  71.                         }  

  72.                     }  

  73.                     catch (Exception ex)  

  74.                     {  

  75.                         while (!lockDic.ContainsKey(len))  

  76.                         {  

  77.                             len += lockDic[len];  

  78.                         }  

  79.                     }  

  80.                 }  

  81.                 fs.Seek(len, System.IO.SeekOrigin.Begin);  

  82.                 fs.Write(dataArray, 0, dataArray.Length);  

  83.                 fs.Close();  

  84.             }  

  85.         }  

  86.         /// <summary>  

  87.         /// 写入文件内容  

  88.         /// </summary>  

  89.         /// <param name="content"></param>  

  90.         public void WriteLine(string content)  

  91.         {  

  92.             this.Write(content, System.Environment.NewLine);  

  93.         }  

  94.         /// <summary>  

  95.         /// 写入文件  

  96.         /// </summary>  

  97.         /// <param name="content"></param>  

  98.         public void Write(string content)  

  99.         {  

  100.             this.Write(content, "");  

  101.         }  

  102.     }  

  103. }  


 


 


调用起来很简单,实例化,然后随便调用一个write或writeLine方法!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多