游戏定时器

游戏定时器,定时执行游戏的任务,比如每到新的一天刷新出新的任务,刷新商店的限购等。

C#服务端常用的定时器有

System.Threading.Timer
System.Timers.Timer

后者是前者的包装,而且不好用。它不能定义最近一次发生的时间。

public class MyTimer
{
    //消息id和对应内容
    private static ConcurrentBag<KeyValuePair<int, byte[]>> EventList { get; } = new();
    //是否一直重复执行
    private readonly bool _autoReset;
    //执行次数
    public int Times { get; private set; }
    private readonly Timer _timer;
    private readonly KeyValuePair<int, byte[]> _cookie;

    /// <param name="o"></param>
    /// <param name="dueTime">离最近一次开始时间剩余的时间</param>
    /// <param name="period">时间周期</param>
    /// <param name="autoReset">是否重复执行</param>
    public MyTimer(KeyValuePair<int, byte[]> o, long dueTime, long period, bool autoReset)
    {
        _autoReset = autoReset;
        if (autoReset == false) Times = 1;
        _cookie = o;
        try
        {
            _timer = new Timer(TimerCallback, this, dueTime, period);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

    /// <param name="o"></param>
    /// <param name="dueTime">离最近一次开始时间剩余的时间</param>
    /// <param name="period">时间周期</param>
    /// <param name="times">次数</param>
    public MyTimer(KeyValuePair<int, byte[]> o, long dueTime, long period, int times)
    {
        Times = times;
        _cookie = o;

        try
        {
            _timer = new Timer(TimerCallback, this, dueTime, period);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

    private void TimerCallback(object state)
    {
        var myTimer = (MyTimer) state;
        if (myTimer == null) return;
        
        if (myTimer._autoReset || Times >= 1)
        {
            Times--;
            EventList.Add(myTimer._cookie);
        }
        else
        {
            _timer.Dispose();
        }
    }

    public static void Process()
    {
        if (EventList.TryTake(out var cookie))
        {
            try
            {
                //todo 分发
                MsgManager.Dispatcher(cookie.Key, cookie.Value);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
    }
}

MyTimer.Process()方法放到主循环中循环检测。在主循环里要记得Thread.Sleep(1)。

private static void Main(string[] args)
{
    ...
    while (true)
    {
        ...
        MyTimer.Process()
        Thread.Sleep(1);
    }
}
2021年10月20日 22:40