当前位置:首页 > 行业动态 > 正文

如何在C服务器中高效创建计时器?

在C#服务器中可通过System.Timers.Timer类实现计时器,创建实例后设置Interval属性定义触发间隔,绑定Elapsed事件编写任务逻辑,调用Start方法启动,需注意线程安全及资源释放,结合异步处理可优化性能。

应用场景

  • 限时活动倒计时:如电商促销倒计时。
  • 定时任务调度:每日数据备份、消息推送。
  • 实时数据更新:股票价格、体育赛事直播。

准备工作

  1. 开发环境

    • .NET 6+ SDK
    • Visual Studio 2022+ 或 VS Code
    • ASP.NET Core Web 应用模板
  2. 技术依赖

    • BackgroundService:用于后台任务托管。
    • System.Timers.TimerSystem.Threading.Timer
    • 前端实时通信(可选SignalR)。

实现步骤

创建后台计时器服务

通过继承 BackgroundService 类实现长期运行的后台计时器。

public class TimerService : BackgroundService
{
    private Timer _timer;
    private readonly ILogger<TimerService> _logger;
    public TimerService(ILogger<TimerService> logger)
    {
        _logger = logger;
    }
    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(1));
        return Task.CompletedTask;
    }
    private void DoWork(object state)
    {
        _logger.LogInformation($"服务器时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
        // 业务逻辑:更新数据库、触发事件等
    }
    public override void Dispose()
    {
        _timer?.Dispose();
        base.Dispose();
    }
}

注册后台服务

Program.cs 中添加服务注册:

builder.Services.AddHostedService<TimerService>();

前端与服务器交互

SignalR 实时推送

  • 创建SignalR Hub

    public class TimeHub : Hub
    {
        public async Task SendTimeToClients()
        {
            await Clients.All.SendAsync("ReceiveTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        }
    }
  • 注册SignalR服务

    builder.Services.AddSignalR();
    app.MapHub<TimeHub>("/timeHub");
  • 前端代码(JavaScript)

    <div id="serverTime"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.min.js"></script>
    <script>
        const connection = new signalR.HubConnectionBuilder()
            .withUrl("/timeHub")
            .build();
        connection.on("ReceiveTime", (time) => {
            document.getElementById("serverTime").innerHTML = time;
        });
        connection.start();
    </script>

API轮询(简单版)

  • 创建API接口

    [ApiController]
    [Route("api/[controller]")]
    public class TimeController : ControllerBase
    {
        [HttpGet]
        public IActionResult GetServerTime()
        {
            return Ok(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        }
    }
  • 前端代码(JavaScript)

    setInterval(() => {
        fetch("/api/time")
            .then(response => response.text())
            .then(time => {
                document.getElementById("serverTime").innerHTML = time;
            });
    }, 1000);

注意事项

  1. 线程安全
    • 避免在计时器回调中直接操作共享资源,需使用 lock 或并发集合。
  2. 资源释放
    • 在应用关闭时调用 Dispose() 释放计时器。
  3. 扩展性
    • 分布式部署时需改用 Quartz.NETHangfire 等框架。
  4. 性能优化

    高频任务(如1秒内多次触发)需评估服务器负载。


引用说明

  • Microsoft官方文档:ASP.NET Core BackgroundService
  • SignalR入门指南
  • Timer类线程安全问题
0