Blazor Server中如何优先处理最新地图请求并跳过旧等待任务
解决方案:只处理最新地图钉加载请求
核心思路是维护一个仅保留最新请求的队列机制,确保当前任务完成后只处理最新的有效请求,旧的等待请求直接标记完成,无需执行数据库查询。
关键实现逻辑
- 用
SemaphoreSlim保证同一时间仅执行一个加载任务 - 用
TaskCompletionSource跟踪每个请求的完成状态,新请求到来时直接终结旧的等待请求 - 进入执行阶段前,验证当前请求是否为最新,无效请求直接返回
代码实现示例
public class MapPinLoader { private readonly SemaphoreSlim _executionLock = new SemaphoreSlim(1, 1); private readonly object _stateLock = new object(); private TaskCompletionSource<bool>? _latestPendingRequest; public async Task HandleMapViewChangeAsync(MapViewBounds newBounds) { // 创建当前请求的完成源 var currentRequestTcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously); lock (_stateLock) { // 终结之前的最新等待请求(让旧请求的调用方直接完成) _latestPendingRequest?.TrySetResult(true); // 将当前请求设为最新 _latestPendingRequest = currentRequestTcs; } try { await _executionLock.WaitAsync(); lock (_stateLock) { // 如果当前请求已经不是最新的,直接退出,不执行查询 if (_latestPendingRequest != currentRequestTcs) { return; } } // 执行耗时的数据库查询 var newPins = await FetchPinsFromDbAsync(newBounds); // Blazor中更新UI需确保在主线程 await UpdateMapPinsInUiAsync(newPins); } finally { lock (_stateLock) { // 标记当前请求完成 currentRequestTcs.TrySetResult(true); // 如果处理过程中又有新请求进来,下一次WaitAsync会自动处理最新的 } _executionLock.Release(); } } // 模拟数据库查询逻辑 private async Task<List<MapPin>> FetchPinsFromDbAsync(MapViewBounds bounds) { // 替换为你的实际查询代码,耗时4-10秒 await Task.Delay(6000); return new List<MapPin>(); } // 模拟Blazor UI更新逻辑 private async Task UpdateMapPinsInUiAsync(List<MapPin> pins) { // 在Blazor组件中需调用InvokeAsync确保线程安全 // await InvokeAsync(() => { /* 更新组件内的地图钉集合 */ }); } } // 地图视图边界模型 public class MapViewBounds { public double MinLatitude { get; set; } public double MaxLatitude { get; set; } public double MinLongitude { get; set; } public double MaxLongitude { get; set; } } // 地图钉模型 public class MapPin { public double Latitude { get; set; } public double Longitude { get; set; } public string Label { get; set; } = string.Empty; }
使用说明
- 在Blazor组件中实例化
MapPinLoader(可通过依赖注入注册为单例/作用域服务) - 用户滚动/缩放地图时,调用
HandleMapViewChangeAsync并传入当前地图边界 - 旧的等待请求会自动被终结,无需等待无效的查询结果
内容的提问来源于stack exchange,提问作者David Thielen
相关产品推荐
相关产品推荐

