C# 批量任務隊列

在實際項目中,需要批量處理一定數量的隊列數據,而不是,一個一個處理,來提高效率。

但是,默認是不支持的。這個時候,就需要這樣的一個業務邏輯對象。

    /// <summary>
    /// 任務隊列接口
    /// </summary>
    public interface ITaskQueue<T>
    {
        /// <summary>
        /// 增加一個對象
        /// </summary>
        /// <param name="t"></param>
        void Add(T t);
        /// <summary>
        /// 獲取一個分組隊列
        /// </summary>
        /// <returns></returns>
        IList<T> GetQueue();
        /// <summary>
        /// 是否阻塞增加
        /// </summary>
        /// <returns></returns>
        bool IsWaitAdd();
        /// <summary>
        /// 當前隊列完成
        /// </summary>
        void Complete();
    }
    /// <summary>
    /// 任務隊列
    /// </summary>
    public class TaskQueue<T> : ITaskQueue<T>, IDisposable
    {
        /// <summary>
        /// 內置隊列
        /// </summary>
        private ConcurrentDictionary<int, IList<T>> taskQueues;
        /// <summary>
        /// 分區大小
        /// </summary>
        private int PartitionSize;
        /// <summary>
        /// 默認index爲0
        /// </summary>
        private int Index = 0;
        /// <summary>
        /// 默認處理偏移
        /// </summary>
        private int OffSet = 0;
        /// <summary>
        /// 內置鎖
        /// </summary>
        private object Lock = new object();
        /// <summary>
        /// <summary>
        /// 構造
        /// </summary>
        /// <param name="PartitionSize">分區大小,默認分區大小爲10 </param>
        public TaskQueue(int PartitionSize = 10)
        {
            taskQueues = new ConcurrentDictionary<int, IList<T>>();
            this.PartitionSize = PartitionSize;
            List<T> ts = new List<T>();
            taskQueues.AddOrUpdate(Index, ts, (k, v) => ts);
        }
        /// <summary>
        /// 增加一個對象
        /// </summary>
        /// <param name="t"></param>
        public void Add(T t)
        {
            lock (Lock)
            {
                IList<T> ts;
                if (taskQueues.TryGetValue(Index, out ts))
                {
                    if (ts.Count < PartitionSize)
                    {
                        ts.Add(t);
                        taskQueues.AddOrUpdate(Index, ts, (k, v) => ts);
                    }
                    else //超出區域範圍,則新建區
                    {
                        Index++;
                        IList<T> ts1 = new List<T>();
                        ts1.Add(t);
                        taskQueues.AddOrUpdate(Index, ts1, (k, v) => ts1);
                    }
                }
                else
                {
                    IList<T> ts1 = new List<T>();
                    ts1.Add(t);
                    taskQueues.AddOrUpdate(Index, ts1, (k, v) => ts1);
                }
            }
        }
        /// <summary>
        /// 獲取一個分組隊列
        /// </summary>
        /// <returns></returns>
        public IList<T> GetQueue()
        {
            lock (Lock)
            {
                IList<T> ts;
                if (taskQueues.TryGetValue(OffSet, out ts))
                {
                    if (OffSet == Index)//如果直接獲取一個能用的,那就新建區爲新區
                    {
                        Index++;
                    }
                    return ts;
                }
                return null;
            }
        }
        /// <summary>
        /// 是否阻塞增加
        /// </summary>
        /// <returns></returns>
        public bool IsWaitAdd()
        {
            lock (Lock)
            {
                if (OffSet != Index)
                {
                    return true;
                }
                return false;
            }
        }
        /// <summary>
        /// 當前隊列完成
        /// </summary>
        public void Complete()
        {
            lock (Lock)
            {
                IList<T> ts;
                taskQueues.TryRemove(OffSet, out ts);
                if (OffSet < Index)
                {
                    OffSet++;
                }
            }
        }

        public void Dispose()
        {
            if (taskQueues != null)
            {
                taskQueues.Clear();
                taskQueues = null;
            }
        }
    }
    class Program
    {
        static TaskQueue<string> taskQueue;
        static void Main(string[] args)
        {
            taskQueue = new TaskQueue<string>();
            #region 一個一直生產指定大小,另外一個消費  先生產,再消費
            //for (int i = 0; i < 1000; i++)
            //{
            //    taskQueue.Add(i.ToString());
            //}
            ////另外一個按照指定的時間,消費
            //while (true)
            //{
            //    Thread.Sleep(2000);
            //    Console.WriteLine("獲取-----開始獲取到數據!");
            //    var list = taskQueue.GetQueue();
            //    if (list != null)
            //    {
            //        Console.WriteLine($"獲取-----對象狀態:{taskQueue.IsWaitAdd()}已獲取的隊列列表:{string.Join(",", list)}");
            //        Console.WriteLine("獲取-----處理1秒後,提交當前!");
            //        Thread.Sleep(1000);
            //        taskQueue.Complete();
            //        Console.WriteLine("獲取-----已經提交!");
            //    }
            //}
            #endregion
            #region 兩個任務處理,實現 一個生產,一個消費  批量  生產,並消費
            Task.Run(() =>
            {
                for (int i = 0; i < 10000000; i++)
                {
                    taskQueue.Add(i.ToString());
                    Thread.Sleep(100);//一秒插入一條
                    Console.WriteLine($"插入-----隊列狀態:{taskQueue.IsWaitAdd()}");
                    while (taskQueue.IsWaitAdd())//有待處理任務
                    {
                        Console.WriteLine("插入-----任務插入中開始阻塞!");
                        SpinWait.SpinUntil(() => !taskQueue.IsWaitAdd());
                    }
                }
            });

            while (true)
            {
                Thread.Sleep(2000);
                Console.WriteLine("獲取-----開始獲取到數據!");
                var list = taskQueue.GetQueue();
                if (list != null)
                {
                    Console.WriteLine($"獲取-----對象狀態:{taskQueue.IsWaitAdd()}已獲取的隊列列表:{string.Join(",", list)}");
                    Console.WriteLine("獲取-----處理10秒後,提交當前!");
                    Thread.Sleep(1000);
                    taskQueue.Complete();
                    Console.WriteLine("獲取-----已經提交!");
                }
            }
            #endregion
            Console.WriteLine("開始獲取信息!");
            Console.ReadLine();
        }
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章