ASP.NET Core Razor如何不用SignalR/AJAX实现每秒更新页面值持续20秒
实现方案
完全可以实现和PHP flush一致的逐秒输出效果,你当前代码无法逐秒更新的核心原因是:ASP.NET Core Razor默认会等整个视图的代码全部执行完成、拼接好完整的HTML内容后,才会把响应一次性发回客户端,所以20秒的等待全发生在服务端渲染阶段,浏览器端收不到任何分段内容,最终只会一次性拿到全部结果。
不需要学习SignalR,也不需要写复杂的AJAX逻辑,只要关闭响应缓冲、主动分段输出内容并刷到客户端即可,和你之前PHP的实现逻辑几乎一致,具体改法如下:
代码修改
直接替换你原来的cshtml内容即可,WMI读取CPU的逻辑可以直接复用你现有的Model.CPU_Load_WMI实现:
@page @model IndexModel @{ ViewData["Title"] = "Home page"; // 提前设置响应头,关闭缓存避免浏览器/代理缓冲内容 Context.Response.Headers["Cache-Control"] = "no-cache"; Context.Response.ContentType = "text/html; charset=utf-8"; // 先输出页面固定头部结构,立刻刷到客户端 await Context.Response.WriteAsync(@" <!DOCTYPE html> <html> <head> <meta charset=""utf-8"" /> <title>@ViewData["Title"]</title> <link rel=""stylesheet"" href=""~/css/site.css"" /> </head> <body> <div class=""text-center""> "); await Context.Response.Body.FlushAsync(); // 循环20次,每秒输出一次最新CPU值 for (var i = 0; i < 20; i++) { // 替换为你自己的WMI读取CPU逻辑即可 var cpuLoad = Model.CPU_Load_WMI; // 输出JS脚本替换原有内容,和你之前PHP的清屏逻辑一致 await Context.Response.WriteAsync( $"<script>document.querySelector('.text-center').innerHTML = '<p>CPULoad: {cpuLoad}</p>';</script>" ); // 立刻把当前输出的内容推送到客户端 await Context.Response.Body.FlushAsync(); // 异步等待1秒,不要用Thread.Sleep阻塞服务端工作线程 await Task.Delay(1000); } // 补全页面闭合标签 await Context.Response.WriteAsync(@" </div> </body> </html> "); await Context.Response.Body.FlushAsync(); }
注意事项
- 绝对不要在循环里用
Thread.Sleep(1000),它会同步阻塞ASP.NET Core的工作线程,并发量稍高就会把服务端线程池占满,用await Task.Delay(1000)是异步等待,不会占用工作线程资源。 - 每输出一段内容必须调用
await Context.Response.Body.FlushAsync(),否则内容会留在服务端的缓冲里,不会立刻发到客户端。 - 所有响应头设置必须放在第一次输出内容之前,否则会抛出运行时异常。
- 这种实现没有额外依赖,不需要引入任何前端库或者额外服务组件,逻辑完全和你之前的PHP实现对齐,开发成本极低。
内容的提问来源于stack exchange,提问作者Mdarende
相关产品推荐
相关产品推荐

