如何一次阻止一个请求,并在其完成后处理最新的请求,完成较旧的请求而不进行处理?

问题描述 投票:0回答:1

我正在地图上显示图钉。当用户滚动或缩小时,我现在可以显示其他图钉。如果此举将增加 50,000 个引脚,则可能需要 4 - 10 秒,因为数据库查询很复杂,因此可能需要时间。

这一切都在 Blazor 服务器 Web 应用程序中,所有调用都是任务事件,因此用户移动,获取更多引脚开始,UI 保持响应,用户移动更多,发送另一个事件,等等。

我目前使用

SemaphoreSlim
来确保一次仅处理 1 个动作。如果用户的活动水平合理,则可以支持 5 个任务,等待轮到他们获得更多图钉。

但是,如果有 4 个任务等待,则最新的任务才是唯一重要的。如果它被处理,那么显示的地图将显示所有所需的引脚。任何早期等待的任务现在都无关紧要了。

当任务完成并且有 2 个以上等待时我想做的是:

  1. 处理最新任务。
  2. 完成该任务之前的所有任务。
  3. 执行此操作时如果有其他任务出现,请重复。

当有其他任务进来时,我不想取消正在进行的任务,因为显示某些内容比用户不断移动要好,查询不断被取消,没有任何更新。所以先完成那一项,然后处理等待的群体。

我该怎么做?

(我尝试保存请求、它们的参数和日期时间戳,然后进行处理。在互斥锁释放时,检查要运行的每个任务以查看它是否可以返回成功。但我所拥有的是复杂的混乱,我猜是有问题的。)

c# multithreading async-await
1个回答
0
投票

一个想法是放弃

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());
© www.soinside.com 2019 - 2024. All rights reserved.