定时修改列表 服务器版,Unity定时回调(服务端不依赖Update)

服务器的话就没有Update了 所以我们要吧计时器从Mono和他自带的计时方法剥离出来

管理类只做一些简单的调用 启动Update

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

///

/// 支持时间定时,帧定时

/// 定时任务可循环 取消 替换

///

public class TimerSys : MonoBehaviour

{

//单例

public static TimerSys Instance;

PETimer pt = new PETimer();

public void Init()

{

Instance = this;

pt.SetLog((string info)=> {

Debug.Log("PETimerLog" + info);

});

}

private void Update()

{

pt.Update();

}

///

/// 添加一个计时器

///

///

///

///

///

///

public int AddTimeTask(Action callBack, float delay, int count = 1, EPETimeUnit timeUnit = EPETimeUnit.Millisecond)

{

return pt.AddTimeTask(callBack, delay, count, timeUnit);

}

///

/// 移除一个计时器

///

///

///

public bool DeleteTimeTask(int tid)

{

return pt.DeleteTimeTask(tid);

}

///

/// 替换

///

///

///

///

///

///

///

public bool ReplaceTimeTask(int tid, Action callBack, float delay, int count = 1, EPETimeUnit timeUnit = EPETimeUnit.Millisecond)

{

return pt.ReplaceTimeTask(tid, callBack, delay, count, timeUnit);

}

///

/// 添加一个帧计时器

///

///

///

///

///

///

public int AddFrameTask(Action callBack, int delay, int count = 1)

{

return pt.AddFrameTask(callBack, delay, count);

}

///

/// 移除一个帧计时器

///

///

///

public bool DeleteFrameTask(int tid)

{

return pt.DeleteFrameTask(tid);

}

///

/// 替换帧计时器

///

///

///

///

///

///

///

public bool ReplaceFrameTask(int tid, Action callBack, int delay, int count = 1)

{

return pt.ReplaceFrameTask(tid, callBack, delay, count);

}

}

把其他逻辑放到另外的类里面

using System.Collections.Generic;

using System;

public class PETimeTask

{

public int tid;

public double destTime;//单位:毫秒

public Action callBack;

public double delay;

public int count;//次数

public PETimeTask(int tid, double destTime, Action callBack, double delay, int count)

{

this.tid = tid;

this.destTime = destTime;

this.callBack = callBack;

this.count = count;

this.delay = delay;

}

}

public class PEFrameTask

{

public int tid;

public int destFrame;//单位:毫秒

public Action callBack;

public int delay;

public int count;//次数

public PEFrameTask(int tid, int destFrame, Action callBack, int delay, int count)

{

this.tid = tid;

this.destFrame = destFrame;

this.callBack = callBack;

this.count = count;

this.delay = delay;

}

}

public enum EPETimeUnit

{

Millisecond = 0,

Second,

Minute,

Hour,

Day

}

///

/// 支持时间定时,帧定时

/// 定时任务可循环 取消 替换

///

public class PETimer

{

Action taskLog;

//声明锁

static readonly string obj = "lock";

//C#的计时 计算机元年

DateTime startDateTime = new DateTime(1970,1,1,0,0,0);

double nowTime;

int tid;

List tids = new List();

///

/// tid缓存回收

///

List recTids = new List();

///

/// 临时列表 支持多线程操作 错开时间操作 避免使用锁 提升操作效率

///

List tmpTimes = new List();

List taskTimes = new List();

int frameCounter;

List tmpFrames = new List();

List taskFrames = new List();

public PETimer()

{

tids.Clear();

recTids.Clear();

tmpTimes.Clear();

taskTimes.Clear();

tmpFrames.Clear();

taskFrames.Clear();

}

public void Update()

{

CheckTimeTask();

CheckFrameTask();

if (recTids.Count > 0)

{

RecycleTid();

}

}

void CheckTimeTask()

{

//加入缓存区中的定时任务

for (int i = 0; i < tmpTimes.Count; i++)

{

taskTimes.Add(tmpTimes[i]);

}

tmpTimes.Clear();

nowTime = GetUTCMilliseconds();

//遍历检测任务是否到达条件

for (int i = 0; i < taskTimes.Count; i++)

{

PETimeTask task = taskTimes[i];

//nowTime>task.destTime 1 nowTime

if (nowTime.CompareTo(task.destTime)<0)

{

continue;

}

else

{

try

{

//时间到 callBack不为空调用

task.callBack?.Invoke();

}

catch (Exception e)

{

LogInfo(e.ToString());

}

if (task.count == 1)

{

taskTimes.RemoveAt(i);

i--;

recTids.Add(task.tid);

}

else

{

if (task.count != 0)

{

task.count -= 1;

}

//重新赋值时间

task.destTime += task.delay;

}

}

}

}

void CheckFrameTask()

{

//加入缓存区中的定时任务

for (int i = 0; i < tmpFrames.Count; i++)

{

taskFrames.Add(tmpFrames[i]);

}

tmpFrames.Clear();

frameCounter += 1;

//遍历检测任务是否到达条件

for (int i = 0; i < taskFrames.Count; i++)

{

PEFrameTask task = taskFrames[i];

if (frameCounter < task.destFrame)

{

continue;

}

else

{

try

{

//时间到 callBack不为空调用

task.callBack?.Invoke();

}

catch (Exception e)

{

LogInfo(e.ToString());

}

if (task.count == 1)

{

taskFrames.RemoveAt(i);

i--;

recTids.Add(task.tid);

}

else

{

if (task.count != 0)

{

task.count -= 1;

}

//重新赋值时间

task.destFrame += task.delay;

}

}

}

}

#region TimeTask

///

/// 添加一个计时器

///

///

///

///

///

///

public int AddTimeTask(Action callBack, float delay, int count = 1, EPETimeUnit timeUnit = EPETimeUnit.Millisecond)

{

//时间单位换算 最小毫秒

if (timeUnit != EPETimeUnit.Millisecond)

{

switch (timeUnit)

{

case EPETimeUnit.Second:

delay = delay * 1000;

break;

case EPETimeUnit.Minute:

delay = delay * 1000 * 60;

break;

case EPETimeUnit.Hour:

delay = delay * 1000 * 60 * 60;

break;

case EPETimeUnit.Day:

delay = delay * 1000 * 60 * 60 * 24;

break;

default:

LogInfo("Add Task TimeUnit Type error");

break;

}

}

int tid = GetTid();

//从游戏开始到现在的时间

nowTime = GetUTCMilliseconds();

tmpTimes.Add(new PETimeTask(tid, nowTime+delay, callBack, delay, count));

tids.Add(tid);

return tid;

}

///

/// 移除一个计时器

///

///

///

public bool DeleteTimeTask(int tid)

{

bool exist = false;

for (int i = 0; i < taskTimes.Count; i++)

{

PETimeTask task = taskTimes[i];

if (task.tid == tid)

{

taskTimes.RemoveAt(i);

for (int j = 0; j < tids.Count; j++)

{

if (tids[j] == tid)

{

tids.RemoveAt(j);

break;

}

}

exist = true;

break;

}

}

if (!exist)

{

for (int i = 0; i < tmpTimes.Count; i++)

{

PETimeTask task = tmpTimes[i];

if (task.tid == tid)

{

tmpTimes.RemoveAt(i);

for (int j = 0; j < tids.Count; j++)

{

if (tids[j] == tid)

{

tids.RemoveAt(j);

break;

}

}

exist = true;

break;

}

}

}

return exist;

}

///

/// 替换

///

///

///

///

///

///

///

public bool ReplaceTimeTask(int tid, Action callBack, float delay, int count = 1, EPETimeUnit timeUnit = EPETimeUnit.Millisecond)

{

//时间单位换算 最小毫秒

if (timeUnit != EPETimeUnit.Millisecond)

{

switch (timeUnit)

{

case EPETimeUnit.Second:

delay = delay * 1000;

break;

case EPETimeUnit.Minute:

delay = delay * 1000 * 60;

break;

case EPETimeUnit.Hour:

delay = delay * 1000 * 60 * 60;

break;

case EPETimeUnit.Day:

delay = delay * 1000 * 60 * 60 * 24;

break;

default:

LogInfo("Add Task TimeUnit Type error");

break;

}

}

//从游戏开始到现在的时间

nowTime = GetUTCMilliseconds();

PETimeTask newTask = new PETimeTask(tid, nowTime+delay, callBack, delay, count);

bool isRep = false;

for (int i = 0; i < taskTimes.Count; i++)

{

if (taskTimes[i].tid == tid)

{

taskTimes[i] = newTask;

isRep = true;

break;

}

}

if (!isRep)

{

for (int i = 0; i < tmpTimes.Count; i++)

{

if (tmpTimes[i].tid == tid)

{

tmpTimes[i] = newTask;

isRep = true;

break;

}

}

}

return isRep;

}

#endregion

#region FrameTask

///

/// 添加一个帧计时器

///

///

///

///

///

///

public int AddFrameTask(Action callBack, int delay, int count = 1)

{

int tid = GetTid();

taskFrames.Add(new PEFrameTask(tid, frameCounter + delay, callBack, delay, count));

tids.Add(tid);

return tid;

}

///

/// 移除一个帧计时器

///

///

///

public bool DeleteFrameTask(int tid)

{

bool exist = false;

for (int i = 0; i < taskFrames.Count; i++)

{

PEFrameTask task = taskFrames[i];

if (task.tid == tid)

{

taskFrames.RemoveAt(i);

for (int j = 0; j < tids.Count; j++)

{

if (tids[j] == tid)

{

tids.RemoveAt(j);

break;

}

}

exist = true;

break;

}

}

if (!exist)

{

for (int i = 0; i < tmpFrames.Count; i++)

{

PEFrameTask task = tmpFrames[i];

if (task.tid == tid)

{

tmpFrames.RemoveAt(i);

for (int j = 0; j < tids.Count; j++)

{

if (tids[j] == tid)

{

tids.RemoveAt(j);

break;

}

}

exist = true;

break;

}

}

}

return exist;

}

///

/// 替换帧计时器

///

///

///

///

///

///

///

public bool ReplaceFrameTask(int tid, Action callBack, int delay, int count = 1)

{

PEFrameTask newTask = new PEFrameTask(tid, frameCounter + delay, callBack, delay, count);

bool isRep = false;

for (int i = 0; i < taskFrames.Count; i++)

{

if (taskFrames[i].tid == tid)

{

taskFrames[i] = newTask;

isRep = true;

break;

}

}

if (!isRep)

{

for (int i = 0; i < tmpFrames.Count; i++)

{

if (tmpFrames[i].tid == tid)

{

tmpFrames[i] = newTask;

isRep = true;

break;

}

}

}

return isRep;

}

#endregion

public void SetLog(Action log)

{

taskLog = log;

}

#region Tool Methonds

int GetTid()

{

lock (obj)

{

tid += 1;

//安全代码,以防万一(服务器)

while (true)

{

if (tid == int.MaxValue)

{

tid = 0;

}

//最后一个归0后从新赋值唯一id

bool used = false;

for (int i = 0; i < tids.Count; i++)

{

if (tid == tids[i])

{

used = true;

break;

}

}

if (!used)

{

break;

}

else

{

tid += 1;

}

}

}

return tid;

}

///

/// tid回收

///

void RecycleTid()

{

for (int i = 0; i < recTids.Count; i++)

{

int tid = recTids[i];

for (int j = 0; j < tids.Count; j++)

{

if (tids[j] == tid)

{

tids.RemoveAt(j);

break;

}

}

}

recTids.Clear();

}

void LogInfo(string info)

{

taskLog?.Invoke(info);

}

///

/// 获取时间的方法

///

///

double GetUTCMilliseconds()

{

//Now是本机时间

//现在世界标准时间-计算机元年时间

TimeSpan ts = DateTime.UtcNow - startDateTime;

//返回TimeSpan值表示的毫秒数

return ts.TotalMilliseconds;

}

#endregion

}

调用类不用改变

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

///

/// 支持时间定时,帧定时

/// 定时任务可循环 取消 替换

///

public class TimerSys : MonoBehaviour

{

//单例

public static TimerSys Instance;

PETimer pt = new PETimer();

public void Init()

{

Instance = this;

pt.SetLog((string info)=> {

Debug.Log("PETimerLog" + info);

});

}

private void Update()

{

pt.Update();

}

///

/// 添加一个计时器

///

///

///

///

///

///

public int AddTimeTask(Action callBack, float delay, int count = 1, EPETimeUnit timeUnit = EPETimeUnit.Millisecond)

{

return pt.AddTimeTask(callBack, delay, count, timeUnit);

}

///

/// 移除一个计时器

///

///

///

public bool DeleteTimeTask(int tid)

{

return pt.DeleteTimeTask(tid);

}

///

/// 替换

///

///

///

///

///

///

///

public bool ReplaceTimeTask(int tid, Action callBack, float delay, int count = 1, EPETimeUnit timeUnit = EPETimeUnit.Millisecond)

{

return pt.ReplaceTimeTask(tid, callBack, delay, count, timeUnit);

}

///

/// 添加一个帧计时器

///

///

///

///

///

///

public int AddFrameTask(Action callBack, int delay, int count = 1)

{

return pt.AddFrameTask(callBack, delay, count);

}

///

/// 移除一个帧计时器

///

///

///

public bool DeleteFrameTask(int tid)

{

return pt.DeleteFrameTask(tid);

}

///

/// 替换帧计时器

///

///

///

///

///

///

///

public bool ReplaceFrameTask(int tid, Action callBack, int delay, int count = 1)

{

return pt.ReplaceFrameTask(tid, callBack, delay, count);

}

}

a7c3274c54dc

image.png

都没问题 打开VS新建控制台程序

a7c3274c54dc

image.png

a7c3274c54dc

image.png

a7c3274c54dc

image.png

找到路径把之前PETimer代码粘贴过来 这样

a7c3274c54dc

image.png

进入VS

a7c3274c54dc

image.png

选中这俩包括在项目中

a7c3274c54dc

image.png

然后在Program里main函数写调用

然后服务器用计时器定时数量庞大 把计算量分离出来

using System.Collections.Generic;

using System;

using System.Timers;

public class PETimeTask

{

public int tid;

public double destTime;//单位:毫秒

public Action callBack;

public double delay;

public int count;//次数

public PETimeTask(int tid, double destTime, Action callBack, double delay, int count)

{

this.tid = tid;

this.destTime = destTime;

this.callBack = callBack;

this.count = count;

this.delay = delay;

}

}

public class PEFrameTask

{

public int tid;

public int destFrame;//单位:毫秒

public Action callBack;

public int delay;

public int count;//次数

public PEFrameTask(int tid, int destFrame, Action callBack, int delay, int count)

{

this.tid = tid;

this.destFrame = destFrame;

this.callBack = callBack;

this.count = count;

this.delay = delay;

}

}

public enum EPETimeUnit

{

Millisecond = 0,

Second,

Minute,

Hour,

Day

}

///

/// 支持时间定时,帧定时

/// 定时任务可循环 取消 替换

///

public class PETimer

{

Action taskLog;

//声明锁

static readonly string obj = "lock";

//C#的计时 计算机元年

DateTime startDateTime = new DateTime(1970,1,1,0,0,0,0);

double nowTime;

Timer srvTimer;

int tid;

List tids = new List();

///

/// tid缓存回收

///

List recTids = new List();

///

/// 临时列表 支持多线程操作 错开时间操作 避免使用锁 提升操作效率

///

List tmpTimes = new List();

List taskTimes = new List();

int frameCounter;

List tmpFrames = new List();

List taskFrames = new List();

///

///

///

/// 调用运行间隔服务器用

public PETimer(int interval=0)

{

tids.Clear();

recTids.Clear();

tmpTimes.Clear();

taskTimes.Clear();

tmpFrames.Clear();

taskFrames.Clear();

if (interval!=0)

{

srvTimer = new Timer(interval) {

AutoReset = true //设置是否循环

};

srvTimer.Elapsed += (object sender, ElapsedEventArgs arg) => {

Update();

};

srvTimer.Start();

}

}

public void Update()

{

CheckTimeTask();

CheckFrameTask();

if (recTids.Count > 0)

{

RecycleTid();

}

}

void CheckTimeTask()

{

//加入缓存区中的定时任务

for (int i = 0; i < tmpTimes.Count; i++)

{

taskTimes.Add(tmpTimes[i]);

}

tmpTimes.Clear();

nowTime = GetUTCMilliseconds();

//遍历检测任务是否到达条件

for (int i = 0; i < taskTimes.Count; i++)

{

PETimeTask task = taskTimes[i];

//nowTime>task.destTime 1 nowTime

if (nowTime.CompareTo(task.destTime)<0)

{

continue;

}

else

{

try

{

//时间到 callBack不为空调用

task.callBack?.Invoke();

}

catch (Exception e)

{

LogInfo(e.ToString());

}

if (task.count == 1)

{

taskTimes.RemoveAt(i);

i--;

recTids.Add(task.tid);

}

else

{

if (task.count != 0)

{

task.count -= 1;

}

//重新赋值时间

task.destTime += task.delay;

}

}

}

}

void CheckFrameTask()

{

//加入缓存区中的定时任务

for (int i = 0; i < tmpFrames.Count; i++)

{

taskFrames.Add(tmpFrames[i]);

}

tmpFrames.Clear();

frameCounter += 1;

//遍历检测任务是否到达条件

for (int i = 0; i < taskFrames.Count; i++)

{

PEFrameTask task = taskFrames[i];

if (frameCounter < task.destFrame)

{

continue;

}

else

{

try

{

//时间到 callBack不为空调用

task.callBack?.Invoke();

}

catch (Exception e)

{

LogInfo(e.ToString());

}

if (task.count == 1)

{

taskFrames.RemoveAt(i);

i--;

recTids.Add(task.tid);

}

else

{

if (task.count != 0)

{

task.count -= 1;

}

//重新赋值时间

task.destFrame += task.delay;

}

}

}

}

#region TimeTask

///

/// 添加一个计时器

///

///

///

///

///

///

public int AddTimeTask(Action callBack, float delay, int count = 1, EPETimeUnit timeUnit = EPETimeUnit.Millisecond)

{

//时间单位换算 最小毫秒

if (timeUnit != EPETimeUnit.Millisecond)

{

switch (timeUnit)

{

case EPETimeUnit.Second:

delay = delay * 1000;

break;

case EPETimeUnit.Minute:

delay = delay * 1000 * 60;

break;

case EPETimeUnit.Hour:

delay = delay * 1000 * 60 * 60;

break;

case EPETimeUnit.Day:

delay = delay * 1000 * 60 * 60 * 24;

break;

default:

LogInfo("Add Task TimeUnit Type error");

break;

}

}

int tid = GetTid();

//从游戏开始到现在的时间

nowTime = GetUTCMilliseconds();

tmpTimes.Add(new PETimeTask(tid, nowTime+delay, callBack, delay, count));

tids.Add(tid);

return tid;

}

///

/// 移除一个计时器

///

///

///

public bool DeleteTimeTask(int tid)

{

bool exist = false;

for (int i = 0; i < taskTimes.Count; i++)

{

PETimeTask task = taskTimes[i];

if (task.tid == tid)

{

taskTimes.RemoveAt(i);

for (int j = 0; j < tids.Count; j++)

{

if (tids[j] == tid)

{

tids.RemoveAt(j);

break;

}

}

exist = true;

break;

}

}

if (!exist)

{

for (int i = 0; i < tmpTimes.Count; i++)

{

PETimeTask task = tmpTimes[i];

if (task.tid == tid)

{

tmpTimes.RemoveAt(i);

for (int j = 0; j < tids.Count; j++)

{

if (tids[j] == tid)

{

tids.RemoveAt(j);

break;

}

}

exist = true;

break;

}

}

}

return exist;

}

///

/// 替换

///

///

///

///

///

///

///

public bool ReplaceTimeTask(int tid, Action callBack, float delay, int count = 1, EPETimeUnit timeUnit = EPETimeUnit.Millisecond)

{

//时间单位换算 最小毫秒

if (timeUnit != EPETimeUnit.Millisecond)

{

switch (timeUnit)

{

case EPETimeUnit.Second:

delay = delay * 1000;

break;

case EPETimeUnit.Minute:

delay = delay * 1000 * 60;

break;

case EPETimeUnit.Hour:

delay = delay * 1000 * 60 * 60;

break;

case EPETimeUnit.Day:

delay = delay * 1000 * 60 * 60 * 24;

break;

default:

LogInfo("Add Task TimeUnit Type error");

break;

}

}

//从游戏开始到现在的时间

nowTime = GetUTCMilliseconds();

PETimeTask newTask = new PETimeTask(tid, nowTime+delay, callBack, delay, count);

bool isRep = false;

for (int i = 0; i < taskTimes.Count; i++)

{

if (taskTimes[i].tid == tid)

{

taskTimes[i] = newTask;

isRep = true;

break;

}

}

if (!isRep)

{

for (int i = 0; i < tmpTimes.Count; i++)

{

if (tmpTimes[i].tid == tid)

{

tmpTimes[i] = newTask;

isRep = true;

break;

}

}

}

return isRep;

}

#endregion

#region FrameTask

///

/// 添加一个帧计时器

///

///

///

///

///

///

public int AddFrameTask(Action callBack, int delay, int count = 1)

{

int tid = GetTid();

taskFrames.Add(new PEFrameTask(tid, frameCounter + delay, callBack, delay, count));

tids.Add(tid);

return tid;

}

///

/// 移除一个帧计时器

///

///

///

public bool DeleteFrameTask(int tid)

{

bool exist = false;

for (int i = 0; i < taskFrames.Count; i++)

{

PEFrameTask task = taskFrames[i];

if (task.tid == tid)

{

taskFrames.RemoveAt(i);

for (int j = 0; j < tids.Count; j++)

{

if (tids[j] == tid)

{

tids.RemoveAt(j);

break;

}

}

exist = true;

break;

}

}

if (!exist)

{

for (int i = 0; i < tmpFrames.Count; i++)

{

PEFrameTask task = tmpFrames[i];

if (task.tid == tid)

{

tmpFrames.RemoveAt(i);

for (int j = 0; j < tids.Count; j++)

{

if (tids[j] == tid)

{

tids.RemoveAt(j);

break;

}

}

exist = true;

break;

}

}

}

return exist;

}

///

/// 替换帧计时器

///

///

///

///

///

///

///

public bool ReplaceFrameTask(int tid, Action callBack, int delay, int count = 1)

{

PEFrameTask newTask = new PEFrameTask(tid, frameCounter + delay, callBack, delay, count);

bool isRep = false;

for (int i = 0; i < taskFrames.Count; i++)

{

if (taskFrames[i].tid == tid)

{

taskFrames[i] = newTask;

isRep = true;

break;

}

}

if (!isRep)

{

for (int i = 0; i < tmpFrames.Count; i++)

{

if (tmpFrames[i].tid == tid)

{

tmpFrames[i] = newTask;

isRep = true;

break;

}

}

}

return isRep;

}

#endregion

public void SetLog(Action log)

{

taskLog = log;

}

#region Tool Methonds

int GetTid()

{

lock (obj)

{

tid += 1;

//安全代码,以防万一(服务器)

while (true)

{

if (tid == int.MaxValue)

{

tid = 0;

}

//最后一个归0后从新赋值唯一id

bool used = false;

for (int i = 0; i < tids.Count; i++)

{

if (tid == tids[i])

{

used = true;

break;

}

}

if (!used)

{

break;

}

else

{

tid += 1;

}

}

}

return tid;

}

///

/// tid回收

///

void RecycleTid()

{

for (int i = 0; i < recTids.Count; i++)

{

int tid = recTids[i];

for (int j = 0; j < tids.Count; j++)

{

if (tids[j] == tid)

{

tids.RemoveAt(j);

break;

}

}

}

recTids.Clear();

}

void LogInfo(string info)

{

taskLog?.Invoke(info);

}

///

/// 获取时间的方法

///

///

double GetUTCMilliseconds()

{

//Now是本机时间

//现在世界标准时间-计算机元年时间

TimeSpan ts = DateTime.UtcNow - startDateTime;

//返回TimeSpan值表示的毫秒数

return ts.TotalMilliseconds;

}

#endregion

}

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

using System.Threading.Tasks;

using System.Timers;

class Program

{

static void Main(string[] args)

{

//Test1();

//TimerTest();

Test2();

//阻塞让cw显示出来

Console.ReadKey();

}

///

/// 在独立线程检测并处理

///

private static void Test2()

{

PETimer pt = new PETimer(50);

pt.AddTimeTask(() => {

Console.WriteLine($"Time:{DateTime.Now}");

Console.WriteLine($"Process线程ID:{Thread.CurrentThread.ManagedThreadId.ToString()}");

}, 1000, 0);

}

private static void TimerTest()

{

//不声明会有二义性 每隔50毫秒循环一次 看线程ID 里面封装有一个线程池 看谁空闲调用谁

System.Timers.Timer t = new System.Timers.Timer(50);

t.AutoReset = true;//可以一直触发事件

t.Elapsed += (object sender, ElapsedEventArgs arg) => {

Console.WriteLine($"Time:{DateTime.Now}");

Console.WriteLine($"Process线程ID:{Thread.CurrentThread.ManagedThreadId.ToString()}");

};

t.Start();

}

///

/// 在主线程检测并处理

///

private static void Test1()

{

PETimer pt = new PETimer();

pt.SetLog((string info) => {

Console.WriteLine($"ConsoleLog{info}");

});

pt.AddTimeTask(() => {

Console.WriteLine($"Time:{DateTime.Now}");

Console.WriteLine($"Process线程ID:{Thread.CurrentThread.ManagedThreadId.ToString()}");

},1000,0);

while (true)

{

pt.Update();

//休眠20毫秒 不然CPU占用率高

Thread.Sleep(20);

}

}

}

然后就OK了

a7c3274c54dc

image.png

然后因为多线程 加上锁 把数据做安全一点 不然不同线程同时修改就当机了 当然也可能死锁发生

using System.Collections.Generic;

using System;

using System.Timers;

public class PETimeTask

{

public int tid;

public double destTime;//单位:毫秒

public Action callBack;

public double delay;

public int count;//次数

public PETimeTask(int tid, double destTime, Action callBack, double delay, int count)

{

this.tid = tid;

this.destTime = destTime;

this.callBack = callBack;

this.count = count;

this.delay = delay;

}

}

public class PEFrameTask

{

public int tid;

public int destFrame;//单位:毫秒

public Action callBack;

public int delay;

public int count;//次数

public PEFrameTask(int tid, int destFrame, Action callBack, int delay, int count)

{

this.tid = tid;

this.destFrame = destFrame;

this.callBack = callBack;

this.count = count;

this.delay = delay;

}

}

public enum EPETimeUnit

{

Millisecond = 0,

Second,

Minute,

Hour,

Day

}

///

/// 支持时间定时,帧定时

/// 定时任务可循环 取消 替换

///

public class PETimer

{

Action taskLog;

Action, int> taskHandle;

//声明锁

static readonly string lockTid = "lockTid";

//C#的计时 计算机元年

DateTime startDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);

double nowTime;

Timer srvTimer;

int tid;

List tids = new List();

///

/// tid缓存回收

///

List recTids = new List();

static readonly string lockTime = "lockTime";

///

/// 临时列表 支持多线程操作 错开时间操作 避免使用锁 提升操作效率

///

List tmpTimes = new List();

List taskTimes = new List();

List tmpDelTimes = new List();

int frameCounter;

static readonly string lockFrame = "lockFrame";

List tmpFrames = new List();

List taskFrames = new List();

List tmpDelFrames = new List();

///

///

///

/// 调用运行间隔服务器用

public PETimer(int interval = 0)

{

if (interval != 0)

{

srvTimer = new Timer(interval)

{

AutoReset = true //设置是否循环

};

srvTimer.Elapsed += (object sender, ElapsedEventArgs arg) =>

{

Update();

};

srvTimer.Start();

}

}

public void Update()

{

CheckTimeTask();

CheckFrameTask();

DelTimeTask();

DelFrameTask();

if (recTids.Count > 0)

{

lock (lockTid)

RecycleTid();

}

}

void DelFrameTask()

{

if (tmpDelFrames.Count > 0)

{

lock (lockFrame)

{

for (int i = 0; i < tmpDelFrames.Count; i++)

{

bool isDel = false;

int delTid = tmpDelFrames[i];

for (int j = 0; j < taskFrames.Count; j++)

{

if (taskFrames[i].tid == delTid)

{

taskFrames.RemoveAt(j);

recTids.Add(delTid);

isDel = true;

LogInfo("Del taskTimeList ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());

break;

}

}

if (isDel)

{

continue;

}

for (int j = 0; j < tmpFrames.Count; j++)

{

if (tmpFrames[i].tid == delTid)

{

tmpFrames.RemoveAt(j);

recTids.Add(delTid);

LogInfo("Del tmpTimeList ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());

}

}

}

tmpDelFrames.Clear();

}

}

}

void DelTimeTask()

{

if (tmpDelTimes.Count > 0)

{

lock (lockTime)

{

for (int i = 0; i < tmpDelTimes.Count; i++)

{

bool isDel = false;

int delTid = tmpDelTimes[i];

for (int j = 0; j < taskTimes.Count; j++)

{

if (taskTimes[i].tid == delTid)

{

taskTimes.RemoveAt(j);

recTids.Add(delTid);

isDel = true;

LogInfo("Del taskTimeList ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());

break;

}

}

if (isDel)

{

continue;

}

for (int j = 0; j < tmpTimes.Count; j++)

{

if (tmpTimes[i].tid == delTid)

{

tmpTimes.RemoveAt(j);

recTids.Add(delTid);

LogInfo("Del tmpTimeList ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());

}

}

}

tmpDelTimes.Clear();

}

}

}

void CheckTimeTask()

{

//增加临时列表 因为服务器循环比update快 为了数据安全

if (tmpTimes.Count > 0)

{

lock (lockTime)

{

//加入缓存区中的定时任务

for (int i = 0; i < tmpTimes.Count; i++)

{

taskTimes.Add(tmpTimes[i]);

}

tmpTimes.Clear();

}

}

nowTime = GetUTCMilliseconds();

//遍历检测任务是否到达条件

for (int i = 0; i < taskTimes.Count; i++)

{

PETimeTask task = taskTimes[i];

//nowTime>task.destTime 1 nowTime

if (nowTime.CompareTo(task.destTime) < 0)

{

continue;

}

else

{

try

{

if (taskHandle != null)

{

taskHandle(task.callBack, task.tid);

}

else

{

//时间到 callBack不为空调用

task.callBack?.Invoke(task.tid);

}

}

catch (Exception e)

{

LogInfo(e.ToString());

}

if (task.count == 1)

{

taskTimes.RemoveAt(i);

i--;

recTids.Add(task.tid);

}

else

{

if (task.count != 0)

{

task.count -= 1;

}

//重新赋值时间

task.destTime += task.delay;

}

}

}

}

void CheckFrameTask()

{

if (tmpFrames.Count > 0)

{

lock (lockFrame)

{

//加入缓存区中的定时任务

for (int i = 0; i < tmpFrames.Count; i++)

{

taskFrames.Add(tmpFrames[i]);

}

tmpFrames.Clear();

}

}

frameCounter += 1;

//遍历检测任务是否到达条件

for (int i = 0; i < taskFrames.Count; i++)

{

PEFrameTask task = taskFrames[i];

if (frameCounter < task.destFrame)

{

continue;

}

else

{

try

{

if (taskHandle != null)

{

taskHandle(task.callBack, task.tid);

}

else

{

//时间到 callBack不为空调用

task.callBack?.Invoke(task.tid);

}

}

catch (Exception e)

{

LogInfo(e.ToString());

}

if (task.count == 1)

{

taskFrames.RemoveAt(i);

i--;

recTids.Add(task.tid);

}

else

{

if (task.count != 0)

{

task.count -= 1;

}

//重新赋值时间

task.destFrame += task.delay;

}

}

}

}

#region TimeTask

///

/// 添加一个计时器

///

///

///

///

///

///

public int AddTimeTask(Action callBack, float delay, int count = 1, EPETimeUnit timeUnit = EPETimeUnit.Millisecond)

{

ChangeTimeWithType(ref delay, timeUnit);

int tid = GetTid();

//从游戏开始到现在的时间

nowTime = GetUTCMilliseconds();

lock (lockTime)

tmpTimes.Add(new PETimeTask(tid, nowTime + delay, callBack, delay, count));

return tid;

}

///

/// 移除一个计时器

///

///

///

public void DeleteTimeTask(int tid)

{

lock (lockTime)

{

tmpDelTimes.Add(tid);

LogInfo("TmpDel ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString());

}

}

///

/// 替换 不涉及数据增删不用去改 自己改的慢就完蛋

///

///

///

///

///

///

///

public bool ReplaceTimeTask(int tid, Action callBack, float delay, int count = 1, EPETimeUnit timeUnit = EPETimeUnit.Millisecond)

{

ChangeTimeWithType(ref delay, timeUnit);

//从游戏开始到现在的时间

nowTime = GetUTCMilliseconds();

PETimeTask newTask = new PETimeTask(tid, nowTime + delay, callBack, delay, count);

bool isRep = false;

for (int i = 0; i < taskTimes.Count; i++)

{

if (taskTimes[i].tid == tid)

{

taskTimes[i] = newTask;

isRep = true;

break;

}

}

if (!isRep)

{

for (int i = 0; i < tmpTimes.Count; i++)

{

if (tmpTimes[i].tid == tid)

{

tmpTimes[i] = newTask;

isRep = true;

break;

}

}

}

return isRep;

}

#endregion

#region FrameTask

///

/// 添加一个帧计时器

///

///

///

///

///

///

public int AddFrameTask(Action callBack, int delay, int count = 1)

{

int tid = GetTid();

lock (lockFrame)

taskFrames.Add(new PEFrameTask(tid, frameCounter + delay, callBack, delay, count));

return tid;

}

///

/// 移除一个帧计时器

///

///

///

public void DeleteFrameTask(int tid)

{

lock (lockFrame)

{

tmpDelFrames.Add(tid);

}

}

///

/// 替换帧计时器

///

///

///

///

///

///

///

public bool ReplaceFrameTask(int tid, Action callBack, int delay, int count = 1)

{

PEFrameTask newTask = new PEFrameTask(tid, frameCounter + delay, callBack, delay, count);

bool isRep = false;

for (int i = 0; i < taskFrames.Count; i++)

{

if (taskFrames[i].tid == tid)

{

taskFrames[i] = newTask;

isRep = true;

break;

}

}

if (!isRep)

{

for (int i = 0; i < tmpFrames.Count; i++)

{

if (tmpFrames[i].tid == tid)

{

tmpFrames[i] = newTask;

isRep = true;

break;

}

}

}

return isRep;

}

#endregion

public void SetLog(Action log)

{

taskLog = log;

}

public void SetHandle(Action, int> handle)

{

taskHandle = handle;

}

///

/// 重置

///

public void Reset()

{

tid = 0;

tids.Clear();

recTids.Clear();

tmpTimes.Clear();

taskTimes.Clear();

tmpFrames.Clear();

taskFrames.Clear();

taskLog = null;

srvTimer.Stop();

}

//累加而不是 now now的话打断点也会变化

public DateTime GetLocalDateTime()

{

return TimeZone.CurrentTimeZone.ToLocalTime(startDateTime.AddMilliseconds(nowTime));

}

public double GetMillisendsTime()

{

return nowTime;

}

public int GetYear()

{

return GetLocalDateTime().Year;

}

public int GetMonth()

{

return GetLocalDateTime().Month;

}

public int GetDay()

{

return GetLocalDateTime().Day;

}

public int GetDayOfWeek()

{

return (int)GetLocalDateTime().DayOfWeek;

}

public string GetLocalTimeStr()

{

DateTime dt = GetLocalDateTime();

string str = $"{GetTimeStr(dt.Hour)}:{GetTimeStr(dt.Minute)}:{GetTimeStr(dt.Second)}";

return str;

}

#region Tool Methonds

int GetTid()

{

lock (lockTid)

{

tid += 1;

//安全代码,以防万一(服务器)

while (true)

{

if (tid == int.MaxValue)

{

tid = 0;

}

//最后一个归0后从新赋值唯一id

bool used = false;

for (int i = 0; i < tids.Count; i++)

{

if (tid == tids[i])

{

used = true;

break;

}

}

if (!used)

{

tids.Add(tid);

break;

}

else

{

tid += 1;

}

}

}

return tid;

}

///

/// tid回收

///

void RecycleTid()

{

for (int i = 0; i < recTids.Count; i++)

{

int tid = recTids[i];

for (int j = 0; j < tids.Count; j++)

{

if (tids[j] == tid)

{

tids.RemoveAt(j);

break;

}

}

}

recTids.Clear();

}

void LogInfo(string info)

{

taskLog?.Invoke(info);

}

///

/// 获取时间的方法

///

///

double GetUTCMilliseconds()

{

//Now是本机时间

//现在世界标准时间-计算机元年时间

TimeSpan ts = DateTime.UtcNow - startDateTime;

//返回TimeSpan值表示的毫秒数

return ts.TotalMilliseconds;

}

void ChangeTimeWithType(ref float delay, EPETimeUnit timeUnit)

{

//时间单位换算 最小毫秒

if (timeUnit != EPETimeUnit.Millisecond)

{

switch (timeUnit)

{

case EPETimeUnit.Second:

delay = delay * 1000;

break;

case EPETimeUnit.Minute:

delay = delay * 1000 * 60;

break;

case EPETimeUnit.Hour:

delay = delay * 1000 * 60 * 60;

break;

case EPETimeUnit.Day:

delay = delay * 1000 * 60 * 60 * 24;

break;

default:

LogInfo("Add Task TimeUnit Type error");

break;

}

}

}

string GetTimeStr(int time)

{

if (time < 10)

{

return $"0{time}";

}

else

{

return time.ToString();

}

}

#endregion

}

a7c3274c54dc

image.png

然后我自己优化了下很简单的 没用泛型反射因为这样会影响性能 毕竟服务器可是管所有客户端 客户端的计时器优化差点也没问题

这个是源码

https://github.com/1004019267/PETimer/tree/master

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值