• C#多线程写日志


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

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

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

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

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

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

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

    以上几种方法缺点:

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

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

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

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

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

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

  • 相关阅读:
    利用SuperMap Deskpro进行Peking 54到WGS84的转换
    远程序列化xml文件(可用于自动更新程序中版本号的比较,更新文件的读取等)
    [转]C#导出到EXCEL
    [转]常用数学公式
    CLR Via C#系列学习笔记之委托
    黑马程序员C#语言中的三种循环:while 循环、dowhile 循环、for 循环。
    .net2005中GridView或者Datalist等超級流行的分頁
    Array.splice()删除数组中重复的数据
    .net中常需对文件夹以及常用的操作方法
    文件的上传下载示例
  • 原文地址:https://www.cnblogs.com/cxd4321/p/3934294.html
Copyright © 2020-2023  润新知