概述
当Stopwatch的属性ElapsedMilliseconds(单位:ms毫秒)一直增加时,会溢出,虽然过程很长,但是只要程序不中断肯定会溢出。
为了解决这个问题,利用集合进位的思想存。
首先看看这个类所有的成员
是不是很简单?实际代码就180多行,太简单了。
里面注释的很详细就不啰嗦介绍了,直接上代码
public class TimerCenterCarry
{
/// <summary>
/// 实例同步锁
/// </summary>
static readonly object instanceSynObj = new object();
/// <summary>
/// 唯一实例
/// </summary>
static TimerCenterCarry instance;
/// <summary>
/// 服务端唯一实例
/// </summary>
public static TimerCenterCarry Instance
{
get
{
if (instance == null)
{
lock (instanceSynObj)
{
if (instance == null)
{
instance = new TimerCenterCarry();
}
}
}
return instance;
}
}
List<long> TimerCarry;
private Stopwatch sw;
/// <summary>
/// 定义长度
/// </summary>
long _longMaxValueHalf = 0L;
/// <summary>
/// 判断程序是否启动
/// </summary>
bool _isStart = false;
/// <summary>
/// 进位记录第一位值
/// </summary>
long first = 0L;
/// <summary>
/// 私有构造函数
/// </summary>
private TimerCenterCarry()
{
sw = new Stopwatch();
TimerCarry = new List<long>();
}
/// <summary>
/// 后台任务定时器,定期检测Stopwatch,防止Stopwatch溢出
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
// 加锁,防止检查线程与调用线程冲突
lock (this)
{
CalculationTime(sw.ElapsedMilliseconds);
}
}
/// <summary>
/// 逻辑函数
/// </summary>
/// <param name="curTime"></param>
private void CalculationTime(long curTime)
{
curTime += first;
RecursionTime(curTime);
if (curTime > _longMaxValueHalf)
{
sw.Restart();
}
}
/// <summary>
/// 递归自动进位
/// </summary>
/// <param name="curValue"></param>
/// <param name="startIndex"></param>
private void RecursionTime(long curValue, int startIndex = 1)
{
// 添加容器
if (TimerCarry.Count==0
|| (TimerCarry.Count == 1 && curValue > _longMaxValueHalf)
|| (TimerCarry.Count > 1 && (TimerCarry.Last() + 1) > _longMaxValueHalf))
{
// 防止一开始值很大
if (TimerCarry.Count == 0 && curValue > _longMaxValueHalf)
{
var num = GetContainerNum(curValue);
while (num-- > 0)
{
TimerCarry.Add(0);
}
}
TimerCarry.Add(0);
}
// 值未超过定义的值
if (curValue <= _longMaxValueHalf)
{
TimerCarry[startIndex - 1] = curValue;
return;
}
// 值超过定义的值,做进位
TimerCarry[startIndex] = TimerCarry[startIndex] + 1;
// 防止超出
RecursionTime(TimerCarry[startIndex], startIndex + 1);
TimerCarry[startIndex - 1] = curValue - _longMaxValueHalf;
// 防止超出
RecursionTime(TimerCarry[startIndex - 1], startIndex);
// 进位后需要把第一位的数字记录
first = TimerCarry.First();
}
private long GetContainerNum(long curValue)
{
long value = curValue / _longMaxValueHalf;
if (value < _longMaxValueHalf)
return 1;
else if (value == _longMaxValueHalf)
return 2;
else
return 2 + GetContainerNum(value) ;
}
/// <summary>
/// 启动程序
/// </summary>
/// <param name="interval">默认半个月检查一次1296000000</param>
/// <param name="longMaxValueHalf">默认long.MaxValue的一半</param>
/// <exception cref="Exception"></exception>
public void Start(double interval= 1296000000, long longMaxValueHalf= long.MaxValue>>1)
{
if (longMaxValueHalf > long.MaxValue >> 1)
throw new Exception("longMaxValueHalf值不能比long.MaxValue的一半还大");
_longMaxValueHalf=longMaxValueHalf;
_isStart=true;
sw.Start();
Timer myTimer = new Timer(interval);
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(TimerElapsed);
myTimer.AutoReset = true;
myTimer.Enabled = true;
myTimer.Start();
}
/// <summary>
/// 获取自定义长度
/// </summary>
public long GetLongMaxValueHalf => this._longMaxValueHalf;
/// <summary>
/// 判断Stopwatch timer是否在运行
/// </summary>
public bool StopwatchIsRunning => sw.IsRunning;
public void StopwatchRestart()
{
sw.Restart();
}
public void StopwatchStop()
{
sw.Stop();
}
public void StopwatchStart()
{
sw.Start();
}
/// <summary>
/// 获取当前时间
/// </summary>
public List<long> GetTimesNow
{
get
{
if (!_isStart)
throw new Exception("程序未启动,请先启动!");
// 加锁,防止检查线程与调用线程冲突,因为List线程不安全
lock (this)
{
CalculationTime(sw.ElapsedMilliseconds);
}
return TimerCarry;
}
}
}
最后
以上就是淡定口红为你收集整理的C#计时,使用Stopwatch加List进位的全部内容,希望文章能够帮你解决C#计时,使用Stopwatch加List进位所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复