C#多線程寫日志


由於程序是3層架構的,所有多線程記錄日志成了比較棘手的問題,以前還真就沒有在意過寫日志的問題,認為不過是寫文件罷了~~!如今發現原來要實現文件共享,並且能夠使多線程同時操作日志還不能相互沖突,真的很麻煩。當然要實現它我首先想到的是在網上搜,結果可能是我搜的不得其法,沒發現結果,多數都是用lock,mutx等線程鎖或互斥的方式寫日志,偶想這樣和單線程有啥區別嗎?還是沒能起到多線程應該有的效率!

后來問朋友,發現個log4net的東西,不過此物依然用到了線程互斥,看了源碼發現的!

網絡不行,朋友不知道,只好自己想辦法。想了幾種方法如下:

1、寫多個文件,然后找個機會把這些文件合並!

2、干脆放棄寫文件,改寫數據庫!

3、把文件看成一個表結構,實現行級鎖。也就是一個線程寫一行。

4、把文件看成內存塊,每塊寫完再合並!

以上幾種方法缺點:

1、多個文件。。。想起來就惡心!

2、寫數據庫?太沒技術含量咱不干!

3、行級鎖?我一個線程要寫入多行不是看起來很亂?

4、沒想到啥缺點,實現它吧!

以下是偶經過了10000線程並發測試,也沒發現問題的代碼!

 

[c-sharp]  view plain copy print ?
 
  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方法!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM