天天看點

Queue插入的時候報錯:源數組長度不足。請檢查 srcIndex 和長度以及數組的下限。

異常問題記錄:

本想自己手動實作一個日志記錄功能。使用Queue隊列集合來實作多線程的日志記錄。

測試 一個線程寫入資料Enqueue和一個線程讀取資料Dequeue ,直接用的無休眠死循環。

終于抛出異常:源數組長度不足。請檢查 srcIndex 和長度以及數組的下限。

于是百度之。百度結果  說是多線程寫入資料 需要鎖定操作

lock。

嘗試後無效果   依然報異常。

最後解決辦法  是 在 Queue 讀和 都加上鎖定。測試N多線程同時寫入和讀錯都能正常。

LogModel類

Queue插入的時候報錯:源數組長度不足。請檢查 srcIndex 和長度以及數組的下限。
Queue插入的時候報錯:源數組長度不足。請檢查 srcIndex 和長度以及數組的下限。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;

namespace Common.Helper.LogHelper
{
    /// <summary>
    /// 日志模型
    /// </summary>
    public class LogModel
    {
        /// <summary>
        /// 日志要存的路徑 預設路徑:網站根目錄 + Log 檔案夾
        /// </summary>
        public string logFilePath = HttpContext.Current.Server.MapPath("~/") + @"\Log\";

        private string _logFileName;

        /// <summary>
        /// 日志檔案名字
        /// </summary>
        public string logFileName
        {
            get { return _logFileName + "_" + DateTime.Now.ToString("yyyyMMdd"); }
            set { _logFileName = value; }
        }

        private string _logMessg;

        /// <summary>
        /// 日志内容
        /// </summary>
        public string logMessg
        {
            get
            {
                return "====begin====================" + DateTime.Now.ToString() + "====Queue.Count:" + LogHelper.LogQueue.Count + "====================\r\n\r\n"
                    + _logMessg
                    + "\r\n\r\n====end====================" + DateTime.Now.ToString() + "====Queue.Count:" + LogHelper.LogQueue.Count + "===================="
                    + "\r\n\r\n\r\n";
            }
            set { _logMessg = value; }
        }
    }
}      

View Code

LogHelper類

Queue插入的時候報錯:源數組長度不足。請檢查 srcIndex 和長度以及數組的下限。
Queue插入的時候報錯:源數組長度不足。請檢查 srcIndex 和長度以及數組的下限。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Common.Helper.LogHelper
{
    /// <summary>
    /// 日志操作輔助類
    /// [email protected]
    /// 建立20150104 修改20150104
    /// </summary>
    public class LogHelper
    {
        /// <summary>
        /// 消息隊列
        /// </summary>
        private static Queue<LogModel> logQueue = new Queue<LogModel>();
        /// <summary>
        /// 消息隊列 對外隻讀
        /// </summary>
        public static Queue<LogModel> LogQueue
        {
            get { return LogHelper.logQueue; }
        }

        /// <summary>
        /// 标志鎖
        /// </summary>
        static string myLock = "true";

        /// <summary>
        /// 寫入日志檔案
        /// </summary>
        /// <param name="logmede"></param>
        public static void logWrite(LogModel logmede)
        {
            // 這裡需要鎖上 不然會出現:源數組長度不足。請檢查 srcIndex 和長度以及數組的下限。異常   
            //網上有資料說 http://blog.csdn.net/greatbody/article/details/26135057  不能多線程同時寫入隊列
            //其實  不僅僅 不能同時寫入隊列 也不能同時讀和寫如隊列  是以  在Dequeue 取的時候也要鎖定一個對象
            lock (myLock)
                logQueue.Enqueue(logmede);
            logStartWrite();
        }

        /// <summary>
        /// 部分日志檔案大小
        /// </summary>
        public static int SectionlogFileSize = 1024 * 1024 * 1; // 1024Byte * 1024KB * 1MB

        /// <summary>
        /// 變動檔案大小
        /// </summary>
        public static int fileSize = 1024 * 1024 * 4;

        /// <summary>
        /// 檔案編碼格式
        /// </summary>
        public static Encoding encoding = Encoding.Default;

        /// <summary>
        /// 是否開始自動記錄日志
        /// </summary>
        private static bool isStart = false;

        /// <summary>
        /// 開始把隊列消息寫入檔案
        /// </summary>
        private static void logStartWrite()
        {
            if (isStart)
                return;
            isStart = true;
            Thread t = new Thread(delegate()
            {
                while (true)
                {
                    if (LogHelper.logQueue.Count >= 1)
                    {
                        LogModel m = null;
                        lock (myLock)
                            m = LogHelper.logQueue.Dequeue();
                        if (m == null)
                            continue;
                        if (!Directory.Exists(m.logFilePath))
                            Directory.CreateDirectory(m.logFilePath);

                        int i = 0;
                        //部分 日志 檔案路徑
                        string SectionfileFullName = m.logFilePath + m.logFileName + "_" + i.ToString("000") + ".txt";
                        //最新的寫了内容的 部分 日志檔案路徑
                        string TopSectionfileFullName = SectionfileFullName;
                        // 需要實時更新的 最新日志檔案 路徑
                        string LogfileFullNqme = m.logFilePath + m.logFileName + ".txt";

                        FileInfo file = new FileInfo(SectionfileFullName);
                        while (file.Exists && file.Length >= LogHelper.SectionlogFileSize)
                        {
                            TopSectionfileFullName = SectionfileFullName;
                            i++;
                            SectionfileFullName = m.logFilePath + m.logFileName + "_" + i.ToString("000") + ".txt";
                            file = new FileInfo(SectionfileFullName);
                        }

                        try
                        {
                            if (!file.Exists)//如果不存在 這個檔案 就說明需要 建立新的部分日志檔案了
                            {
                                //因為SectionfileFullName路徑的檔案不存在    是以建立
                                File.WriteAllText(SectionfileFullName, m.logMessg, encoding);

                                FileInfo Logfile = new FileInfo(LogfileFullNqme);
                                if (Logfile.Exists && Logfile.Length >= LogHelper.fileSize)
                                    //先清空  然後加上 上一個部分檔案的内容
                                    File.WriteAllText(LogfileFullNqme, File.ReadAllText(TopSectionfileFullName, encoding), encoding);//如果存在則覆寫                           
                            }
                            else
                                File.AppendAllText(SectionfileFullName, m.logMessg, encoding);//累加

                            //追加這次内容 到動态更新的日志檔案
                            File.AppendAllText(LogfileFullNqme, m.logMessg, encoding);
                        }
                        catch (Exception ex)
                        {
                            throw ex;
                        }

                    }
                    else
                    {
                        isStart = false;//标記下次可執行
                        break;//跳出循環
                    }
                }
            });
            t.Start();
        }
    }
}      
  • 學習本是一個不斷抄襲、模仿、練習、創新的過程。
  • 雖然,園中已有本人無法超越的同主題博文,為什麼還是要寫。
  • 對于自己,博文隻是總結。在總結的過程發現問題,解決問題。
  • 對于他人,在此過程如果還能附帶幫助他人,那就再好不過了。
  • 由于部落客能力有限,文中可能存在描述不正确,歡迎指正、補充!
  • 感謝您的閱讀。如果文章對您有用,那麼請輕輕點個贊,以資鼓勵。
  • 工控物聯Q群:995475200

繼續閱讀