You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core中BackgroundService缓存报错:SemaphoreFullException异常

问题分析与修复

异常根源

你遇到的SemaphoreFullException是因为信号量的释放次数超过了获取次数:

  • CacheSignal<T>中的SemaphoreSlim初始计数为1,最大计数也为1。
  • CacheWorker.StartAsync中提前调用了_cacheSignal.WaitAsync(),将信号量计数从1减为0。
  • 第一次ExecuteAsync循环结束时,finally块中的Release()将计数恢复为1。
  • 第二次循环时,代码没有重新获取信号量(未调用WaitAsync()),直接执行Release(),尝试将计数从1加至2,超过了最大计数1,触发异常。

修复方案

步骤1:移除StartAsync中多余的信号量获取

删除CacheWorker.StartAsync里的await _cacheSignal.WaitAsync();,该操作会提前占用信号量且无对应释放逻辑,破坏了"获取-释放"的配对关系。

修改后的StartAsync:

public override async Task StartAsync(CancellationToken cancellationToken)
{
    await base.StartAsync(cancellationToken);
}

步骤2:在ExecuteAsync循环中正确配对信号量操作

每次缓存更新前先获取信号量,确保"获取-释放"严格配对,避免重复释放。修改ExecuteAsync:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        await _cacheSignal.WaitAsync(stoppingToken);
        try
        {
            WeatherForecast[]? forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = Random.Shared.Next(-20, 55),
                    Summary = Summaries[Random.Shared.Next(Summaries.Length)]
                })
                .ToArray();

            _cache.Set("FORECASTS", forecasts);
        }
        finally
        {
            _cacheSignal.Release();
        }

        try
        {
            await Task.Delay(TimeSpan.FromMinutes(2), stoppingToken);
        }
        catch (OperationCanceledException)
        {
            break;
        }
    }
}

额外说明

WeatherService中的信号量使用逻辑是正确的:每次请求获取信号量,确保缓存更新时请求等待,避免读取未完成的缓存数据,无需修改。

内容的提问来源于stack exchange,提问作者Reinder Wit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 12:00:58