Blazor WebAssembly:实现客户端与服务端时间同步
最简单的解决方案:传递已流逝时长而非绝对开始时间
核心思路是绕开客户端与服务端的绝对时间同步问题,改用相对时间差来计算计时器数值:
- 服务端不再返回存储的绝对启动时间,而是直接计算并返回「从启动时刻到当前服务端时间的已流逝秒数」
- 客户端拿到这个初始已流逝时长后,记录自己本地的当前时间作为计时基准点
- 后续客户端只需要用「本地当前时间与基准点的差值」加上「服务端返回的初始时长」,就能得到准确的总耗时
具体实现示例
ASP.NET Core API 修改
[HttpGet("timer/elapsed")] public IActionResult GetElapsedTime() { // serverStartTime为服务端已存储的启动时间(建议用UTC时间) var elapsed = (DateTime.UtcNow - serverStartTime).TotalSeconds; return Ok(new { ElapsedSeconds = elapsed }); }
Blazor 客户端逻辑
@page "/" @inject HttpClient Http <h3>已耗时:@_displayTime</h3> @code { private string _displayTime; private double _initialElapsed; private DateTime _clientStart; protected override async Task OnInitializedAsync() { // 从服务端获取初始已流逝时长 var result = await Http.GetFromJsonAsync<ElapsedResponse>("api/timer/elapsed"); _initialElapsed = result.ElapsedSeconds; _clientStart = DateTime.UtcNow; // 启动定时更新 _ = UpdateTimer(); } private async Task UpdateTimer() { while (true) { // 计算本地流逝时间 + 初始时长 var localElapsed = (DateTime.UtcNow - _clientStart).TotalSeconds; var total = _initialElapsed + localElapsed; // 格式化显示 _displayTime = TimeSpan.FromSeconds(total).ToString(@"mm\:ss"); StateHasChanged(); await Task.Delay(1000); } } private class ElapsedResponse { public double ElapsedSeconds { get; set; } } }
额外建议:全程使用UTC时间计算,避免不同时区带来的时间偏差,这个改动成本极低,还能避免很多潜在问题。
内容的提问来源于stack exchange,提问作者Edwin ZAP
相关产品推荐
相关产品推荐

