v10.10.2024.0701 使用IJsonHost改进Json序列化
大石头 编写于 2024-07-01 08:36:34 大石头 提交于 2024-07-01 08:48:33
X
using System;
using System.Threading;
using NewLife.Log;

namespace NewLife.Threading
{
    /// <summary>线程扩展</summary>
    class ThreadX : IDisposable
    {
        #region 属性
        private String _Name;
        /// <summary>名称</summary>
        public String Name { get { return _Name; } set { _Name = value; } }

        private ThreadTask _Task;
        /// <summary>任务</summary>
        public ThreadTask Task { get { return _Task; } set { _Task = value; } }

        private Exception _LastError;
        /// <summary>最后错误</summary>
        public Exception LastError { get { return _LastError; } private set { _LastError = value; } }

        private Boolean _Running;
        /// <summary>是否正在处理任务</summary>
        public Boolean Running { get { return _Running; } set { _Running = value; } }

        //private Boolean _Alive = true;
        /// <summary>是否活动</summary>
        public Boolean IsAlive
        {
            get
            {
                //虽然还没有分配,但是仍然把它当作活动的,因为它“可用”
                if (_Thread == null) return true;

                return _Thread.IsAlive;
            }
        }

        /// <summary>是否能够释放</summary>
        public Boolean CanRelease
        {
            get
            {
                //正在处理任务的不允许释放
                if (Running) return false;

                //半分钟不活动的可以释放
                if (AliveTime.AddSeconds(180) < DateTime.Now) return true;
                return false;
            }
        }
        #endregion

        #region 私有属性
        /// <summary>线程</summary>
        private Thread _Thread;

        private DateTime _StartTime;
        /// <summary>开始时间</summary>
        private DateTime StartTime { get { return _StartTime; } set { _StartTime = value; } }

        private DateTime _AliveTime;
        /// <summary>活动时间</summary>
        private DateTime AliveTime { get { return _AliveTime; } set { _AliveTime = value; } }

        /// <summary>内部控制事件</summary>
        private AutoResetEvent internalEvent = new AutoResetEvent(false);
        #endregion

        #region 方法
        /// <summary>开始</summary>
        public void Start()
        {
            if (internalEvent == null) internalEvent = new AutoResetEvent(false);

            if (_Thread == null || _Thread.ThreadState.Has(ThreadState.Stopped))
            {
                _Thread = new Thread(Work);
                _Thread.Name = Name;
                _Thread.IsBackground = true;
                //_Thread.Priority = ThreadPriority.AboveNormal;
                _Thread.Start();

                //Thread.Sleep(1);//停一会,可能线程还没建好
            }
            else if (_Thread.ThreadState.Has(ThreadState.Unstarted))
            {
                _Thread.Start();
            }

            Running = true;

            // 如果有任务则马上开启
            if (Task != null) internalEvent.Set();
        }

        /// <summary>取消</summary>
        /// <param name="onlytask">是否仅仅取消任务</param>
        public void Abort(Boolean onlytask)
        {
            WriteLog("取消");
            if (_Thread == null) return;

            //取消参数表示是否终止线程,如果只是取消任务,就传false进去
            _Thread.Abort(!onlytask);
            if (internalEvent != null) internalEvent.Set();
        }

        private void Work()
        {
            while (true)
            {
                try
                {
                    //挂起自己,直到下一个任务到来
                    internalEvent.WaitOne(Timeout.Infinite, false);

                    Running = true;

                    //信号量复位
                    internalEvent.Reset();
                    if (Task != null)
                    {
                        var task = Task;
                        WriteLog("新任务" + task.ID);
                        LastError = null;

                        StartTime = DateTime.Now;

                        Task.Method(Task.Argument);
                    }
                }
                catch (ThreadInterruptedException ex)//中断异常,跳出
                {
                    LastError = ex;
                    _Thread = null;
                    internalEvent.Close();
                    internalEvent = null;
                    break;
                }
                catch (ThreadAbortException ex)//取消异常,有可能是终止当前任务而已,不需要跳出
                {
                    LastError = ex;

                    //异常参数指明是否需要终止线程
#if !Android
                    if (ex.ExceptionState != null && (Boolean)ex.ExceptionState)
#endif
                    {
                        _Thread = null;
                        internalEvent.Close();
                        internalEvent = null;
                        break;
                    }
                }
                catch (Exception ex)//其它异常,继续
                {
                    LastError = ex;

                    var e = FindException<ThreadAbortException>(ex);
                    if (e == null)
                        XTrace.WriteException(ex);
                    else
                    {
                        //异常参数指明是否需要终止线程
#if !Android
                        if (e.ExceptionState != null && (Boolean)e.ExceptionState)
#endif
                        {
                            _Thread = null;
                            internalEvent.Close();
                            internalEvent = null;
                            break;
                        }
                    }
                }
                finally
                {
                    //通知事件订阅者,任务已经完成
                    if (OnTaskFinished != null)
                    {
                        //对不信任方法的调用,捕获所有异常,防止因外部方法的错误而导致线程自身崩溃
                        try
                        {
                            OnTaskFinished(this, EventArgs.Empty);
                        }
                        catch { }
                    }

                    //清空任务,防止下一次重复执行
                    Task = null;

                    AliveTime = DateTime.Now;

                    //不管怎么样,都要标志线程不再运行
                    Running = false;
                }
            }
        }
        #endregion

        #region 事件
        /// <summary>任务完成时</summary>
        public event EventHandler<EventArgs> OnTaskFinished;
        #endregion

        #region IDisposable 成员
        private Boolean _isDisposed = false;

        /// <summary>释放资源</summary>
        public void Dispose()
        {
            Dispose(true);
            //上面的代码已经回收本对象的资源,GC不要再回收了
            GC.SuppressFinalize(this);
        }

        /// <summary>释放资源。非用户代码调用时,仅释放非托管资源</summary>
        /// <param name="disposing">是否用户代码调用</param>
        private void Dispose(Boolean disposing)
        {
            if (!_isDisposed)
            {
                _isDisposed = true;

                WriteLog("释放资源:" + Name);
                //释放托管资源
                //if (disposing)
                {
                    if (_Thread != null)
                    {
                        if (Running) _Thread.Abort(true);
                        _Thread = null;
                    }
                    if (internalEvent != null) internalEvent.Close();
                }
                //释放非托管资源
            }
        }

        ~ThreadX()
        {
            Dispose(false);
        }
        #endregion

        #region 重载
        /// <summary>已重载。</summary>
        /// <returns></returns>
        public override string ToString()
        {
            return Name + " " + (Running ? "正在运行" : "休眠");
        }
        #endregion

        #region 辅助函数
        private static void WriteLog(String msg)
        {
            if (Debug) XTrace.WriteLine("线程:" + Thread.CurrentThread.Name + " 信息:" + msg);
        }

        private static Boolean? _Debug;
        /// <summary>是否调试</summary>
        public static Boolean Debug
        {
            get
            {
                if (_Debug != null) return _Debug.Value;

                _Debug = ThreadPoolX.Debug;

                return _Debug.Value;
            }
            set { _Debug = value; }
        }

        /// <summary>查找指定类型的异常</summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ex"></param>
        /// <returns></returns>
        private static T FindException<T>(Exception ex) where T : Exception
        {
            if (ex == null) return null;

            if (ex is T) return ex as T;

            return FindException<T>(ex.InnerException);
        }
        #endregion
    }
}