using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;

namespace ryCommon
{
    /// <summary>
    /// 
    /// </summary>
    public class RyThreadInfo
    {
        /// <summary>
        /// 
        /// </summary>
        public int start = 0;
        /// <summary>
        /// 
        /// </summary>
        public int end = 0;
    }
    /// <summary>
    /// 
    /// </summary>
    public class MultiThread
    {
        /// <summary>
        /// 设置线程数量
        /// </summary>
        public int ThreadCount
        {
            get; set;
        } = 20;
        /// <summary>
        /// 要计算的总数量
        /// </summary>
        public int CalcCount
        { get; set; }
        /// <summary>
        /// 每个线程要计算的数量
        /// </summary>
        public int EveryThreadCalcCount
        {
            get; set;
        }
        /// <summary>
        /// 
        /// </summary>
        public MultiThread()
        { }
        private int CompleCount = 0;
        private int CompleIndex = 0;
        private DateTime startTime;
        /// <summary>
        /// 当前已使用的时间
        /// </summary>
        public TimeSpan UseTime
        {
            get { return (DateTime.Now - startTime); }
        }
        private static readonly object CompleIndexlocker = new object();
        /// <summary>
        /// 
        /// </summary>
        /// <param name="threadCount">线程数量</param>
        /// <param name="calcCount">要计算的事务数量</param>
        public MultiThread(int threadCount, int calcCount)
        {
            ThreadCount = threadCount;
            CalcCount = calcCount;
        }
        private Thread[] _MultiThread;
        /// <summary>
        /// 
        /// </summary>
        public void Start()
        {
            startTime = DateTime.Now;
            int _ThreadCount = ThreadCount;
            //线程数量大于地址总数
            if (ThreadCount > CalcCount)
            {
                _ThreadCount = CalcCount;
            }
            if (_ThreadCount == 0)
            { 
                EveryThreadCalcCount =0;
                OnAllCalcComplete?.Invoke(this, UseTime);
                return;
            }
            else
            {
                EveryThreadCalcCount = (CalcCount / _ThreadCount);
            }
            System.Net.ServicePointManager.DefaultConnectionLimit = 1024;
            if (_MultiThread != null)
            {
                for (int i = 0; i < _MultiThread.Length; i++)
                {
                    if (_MultiThread[i] != null) { _MultiThread[i].Abort(); }
                }
            }
            CompleIndex = 0;
            CompleCount = _ThreadCount;
            _MultiThread = new Thread[_ThreadCount];
            for (int i = 0; i < _ThreadCount; i++)
            {
                _MultiThread[i] = new Thread(new ThreadStart(Calc));
                ryCommon.Storage tStor = new ryCommon.Storage();
                tStor.AddNode2("id", "Info");
                tStor.SetAttrValue("start", EveryThreadCalcCount * i);
                if (i == _ThreadCount - 1)
                {
                    tStor.SetAttrValue("end", (CalcCount - 1).ToString());
                }
                else
                {

                    tStor.SetAttrValue("end", ((EveryThreadCalcCount * (i + 1)) - 1).ToString());
                }
                tStor.SetAttrValue("index", i.ToString());
                _MultiThread[i].Name = tStor.GetXMLText();
                _MultiThread[i].Start();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void ThreadHandler(object sender, RyThreadInfo e);
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void CompleteHandler(object sender, TimeSpan e);
        /// <summary>
        /// 多线程计算时激发
        /// </summary>
        [Description("多线程计算时激发")]
        public event ThreadHandler OnCalc;
        /// <summary>
        /// 在所有线程执行完毕后发生
        /// </summary>
        [Description("在所有线程执行完毕后发生")]
        public event CompleteHandler OnAllCalcComplete;
        /// <summary>
        /// 在线程执行完毕后发生,最后一个执行完毕的线程将不收到本事件通知
        /// </summary>
        [Description("在线程执行完毕后发生,最后一个执行完毕的线程将不收到本事件通知")]
        public event EventHandler OnCalcComplete;
        private void Calc()
        {
            if(OnCalc!=null)
            {
                RyThreadInfo item = new RyThreadInfo();
                ryCommon.Storage tStor = new ryCommon.Storage(Thread.CurrentThread.Name);
                tStor.SelectNode2("id", "Info");
                item.start = tStor.GetAttrValueByInt("start", 0);
                item.end = tStor.GetAttrValueByInt("end", 0);
                OnCalc(this, item);
            }
            lock (CompleIndexlocker)
            {
                CompleIndex++;
                if (CompleIndex == CompleCount)
                {
                    OnAllCalcComplete?.Invoke(this, UseTime);
                }
                else
                {
                    OnCalcComplete?.Invoke(this, new EventArgs());
                }
            }
        }
    }
}
