我正在地图上显示图钉。当用户滚动或缩小时,我现在可以显示其他图钉。如果此举将增加 50,000 个引脚,则可能需要 4 - 10 秒,因为数据库查询很复杂,因此可能需要时间。
这一切都在 Blazor 服务器 Web 应用程序中,所有调用都是任务事件,因此用户移动,获取更多引脚开始,UI 保持响应,用户移动更多,发送另一个事件,等等。
我目前使用
SemaphoreSlim
来确保一次仅处理 1 个动作。如果用户的活动水平合理,则可以支持 5 个任务,等待轮到他们获得更多图钉。
但是,如果有 4 个任务等待,则最新的任务才是唯一重要的。如果它被处理,那么显示的地图将显示所有所需的引脚。任何早期等待的任务现在都无关紧要了。
当任务完成并且有 2 个以上等待时我想做的是:
当有其他任务进来时,我不想取消正在进行的任务,因为显示某些内容比用户不断移动要好,查询不断被取消,没有任何更新。所以先完成那一项,然后处理等待的群体。
我该怎么做?
(我尝试保存请求、它们的参数和日期时间戳,然后进行处理。在互斥锁释放时,检查要运行的每个任务以查看它是否可以返回成功。但我所拥有的是复杂的混乱,我猜是有问题的。)
一个想法是放弃
SemaphoreSlim
,转而使用异步处理循环,从队列中获取任务并一次处理一个任务。作为队列,您可以使用容量为 1 的有界 Channel<T>
,配置为在没有空间容纳最新项目时丢弃最旧的项目:
Channel<PinRequest> pinRequests = Channel.CreateBounded<PinRequest>(
new BoundedChannelOptions(capacity: 1)
{
FullMode = BoundedChannelFullMode.DropOldest,
});
async Task ProcessPins()
{
await foreach (var pinRequest in channel.Reader.ReadAllAsync())
{
await ProcessPinRequestAsync(pinRequest);
}
}
要在队列中添加新的
PinRequest
:
pinRequests.Writer.TryWrite(new PinRequest());