C# 单例模式基类如何初始化子类 这篇文章中涉及到了线程操作,实际使用时发现如果方法Internal_Start()
中睡眠时间较长(例如10秒),操作时在10秒内先调用stop再调用start方法时,希望停止的线程无法停止.
研究了后发现是因为使用的状态位是全局变量,再次调用start时,上一次的stop调用被改为false的状态位还未生效又被改回true,导致调用stop时应停止的线程无法终止同时又启动了一个新线程.
我的解决方法是增加两个全局变量,一个int
值记录当前是第几次启动线程(从0开始计数,-1表示线程从未启动过),一个bool
值链表记录对应第几次启动的线程状态,线程是否停止使用链表中的标志位判断,int
值作为线程启动参数传入内部,这样外部改变它的值时不会影响线程内部对该值的调用.优化后的完整父类文件如下
优化后父类
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; namespace HuluChajian.ThreadHelper { /// <summary>此单例只能在主线程执行,未做线程安全处理</summary> internal class ThreadHelper<T> where T : class { static T _instance; public static T Instance { get { return _instance == null ? _instance = (T)System.Reflection.Assembly.GetAssembly(typeof(T)).CreateInstance(typeof(T).ToString()) : _instance; } } int _index = -1; /// <summary>记录启动过的线程的标志位,当有线程在运行状态时,此列表应只有最后一个元素为true</summary> protected List<bool> isStartLst = new List<bool>(); /// <summary>标识线程是否已经启动,已经启动值为true</summary> protected bool isStart = false; /// <summary>启动线程</summary> public void Start() { if (isStart) { return; }//已经启动过不能再次启动,直接返回. isStart = true; _index++; isStartLst.Add(isStart); StartTop(_index); } /// <summary>启动时需要调用的自定义方法,需要自行调用线程[一般情况下不重写此方法,重写时需要完全重写此方法,即重写时不可保留 base.StartTop();]</summary> protected virtual void StartTop(int index) { new Thread((o) => { while (isStartLst[(int)o]) { Internal_Start(); } }).Start(index); } /// <summary>启动的线程需要执行的操作,重写时无需保留 base.Internal_Start();</summary> protected virtual void Internal_Start() { Console.WriteLine("启动父线程,线程ID:" + Thread.CurrentThread.ManagedThreadId); Thread.Sleep(1000);//每隔1秒执行一次 } /// <summary>停止线程</summary> public void Stop() { isStart = false; if (_index!=-1) { isStartLst[_index] = false; } Internal_Stop(); } /// <summary>停止线程需要调用的自定义方法,重写时无需保留 base.Internal_Stop();</summary> protected virtual void Internal_Stop() { Console.WriteLine("停止父线程"); } } }
文章评论