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("停止父线程");
}
}
}