上一篇
如何在C服务器中高效创建计时器?
- 行业动态
- 2025-05-12
- 6
在C#服务器中可通过System.Timers.Timer类实现计时器,创建实例后设置Interval属性定义触发间隔,绑定Elapsed事件编写任务逻辑,调用Start方法启动,需注意线程安全及资源释放,结合异步处理可优化性能。
应用场景
- 限时活动倒计时:如电商促销倒计时。
- 定时任务调度:每日数据备份、消息推送。
- 实时数据更新:股票价格、体育赛事直播。
准备工作
开发环境
- .NET 6+ SDK
- Visual Studio 2022+ 或 VS Code
- ASP.NET Core Web 应用模板
技术依赖
BackgroundService
:用于后台任务托管。System.Timers.Timer
或System.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);
注意事项
- 线程安全
- 避免在计时器回调中直接操作共享资源,需使用
lock
或并发集合。
- 避免在计时器回调中直接操作共享资源,需使用
- 资源释放
- 在应用关闭时调用
Dispose()
释放计时器。
- 在应用关闭时调用
- 扩展性
- 分布式部署时需改用
Quartz.NET
或Hangfire
等框架。
- 分布式部署时需改用
- 性能优化
高频任务(如1秒内多次触发)需评估服务器负载。
引用说明
- Microsoft官方文档:ASP.NET Core BackgroundService
- SignalR入门指南
- Timer类线程安全问题