Blazor Server执行后台任务时避免UI冻结与重连问题
解决Blazor Server大量异步任务导致UI冻结的方案
一、修复核心异步逻辑问题
1. 替换同步阻塞为异步等待
Demo类中Thread.Sleep会阻塞线程池线程,导致线程资源被快速耗尽,换成异步等待的Task.Delay,让线程可以被线程池复用:
public class Demo { public int Id; public bool WorkDone { get; set; } public Demo(int id) { this.WorkDone = false; this.Id = id; } public async Task Work() { Random r = new(); await Task.Delay(1000 * r.Next(1, 10)); // 异步等待,不占用线程 this.WorkDone = true; } }
同时去掉原Work方法中多余的Task.Run包装,因为Work本身已经是异步方法。
2. 用异步限流替代AsParallel
AsParallel().ForAll不兼容异步委托,会导致线程池滥用和异步任务失控。改用SemaphoreSlim限制并发数,同时用异步循环处理任务:
@code { // ... 其他代码不变 // 改为异步方法,Blazor支持绑定异步点击事件 public async Task DoWork() { allworkdone = false; await InvokeAsync(StateHasChanged); // 限制同时运行10个任务,可根据服务器配置调整(比如CPU核心数*2) var semaphore = new SemaphoreSlim(10); var tasks = new List<Task>(); foreach (var item in data) { await semaphore.WaitAsync(); tasks.Add(Task.Run(async () => { try { await item.Work(); } finally { semaphore.Release(); await InvokeAsync(StateHasChanged); // 单个任务完成后更新UI } })); } await Task.WhenAll(tasks); allworkdone = true; await InvokeAsync(StateHasChanged); } }
二、优化UI更新频率
10000个任务每个都触发一次UI更新会造成大量重渲染开销,可以改为批量更新:
public async Task DoWork() { allworkdone = false; await InvokeAsync(StateHasChanged); int completedCount = 0; var semaphore = new SemaphoreSlim(10); var tasks = new List<Task>(); foreach (var item in data) { await semaphore.WaitAsync(); tasks.Add(Task.Run(async () => { try { await item.Work(); // 原子操作计数,避免多线程冲突 Interlocked.Increment(ref completedCount); // 每10个任务完成后统一更新UI if (completedCount % 10 == 0) { await InvokeAsync(StateHasChanged); } } finally { semaphore.Release(); } })); } await Task.WhenAll(tasks); allworkdone = true; await InvokeAsync(StateHasChanged); }
三、避免线程池耗尽的关键注意事项
- 仅在处理CPU密集型任务时使用
Task.Run,IO密集型任务直接调用原生异步API即可,不要额外包装。 - 合理设置并发数:根据服务器CPU核心数调整
SemaphoreSlim的初始计数,避免线程池过载。 - 禁止在同步生命周期方法(如
OnInitialized)中执行阻塞操作,所有耗时逻辑都要放在异步方法里。
四、修正原代码的逻辑错误
原代码中allworkdone = true;会在AsParallel.ForAll执行完成后立刻设置,但此时异步任务还在后台运行,导致"Work Done"提示过早出现。必须放在Task.WhenAll之后,才能确保所有任务真正完成。
内容的提问来源于stack exchange,提问作者SolarOsQuiere
相关产品推荐
相关产品推荐

