信号量的多线程问题

Dev*_*est 2 .net c# multithreading semaphore

我需要一段代码,根据参数键只允许同时由 1 个线程执行:

    private static readonly ConcurrentDictionary<string, SemaphoreSlim> Semaphores = new();

    private async Task<TModel> GetValueWithBlockAsync<TModel>(string valueKey, Func<Task<TModel>> valueAction)
    {
        var semaphore = Semaphores.GetOrAdd(valueKey, s => new SemaphoreSlim(1, 1));

        try
        {
            await semaphore.WaitAsync();

            return await valueAction();
        }
        finally
        {
            semaphore.Release(); // Exception here - System.ObjectDisposedException
            if (semaphore.CurrentCount > 0 && Semaphores.TryRemove(valueKey, out semaphore))
            {
                semaphore?.Dispose();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我时不时地收到错误:

The semaphore has been disposed. : System.ObjectDisposedException: The semaphore has been disposed.
   at System.Threading.SemaphoreSlim.CheckDispose()
   at System.Threading.SemaphoreSlim.Release(Int32 releaseCount)
   at Project.GetValueWithBlockAsync[TModel](String valueKey, Func`1 valueAction)
Run Code Online (Sandbox Code Playgroud)

我在这里能想象到的所有情况都是线程安全的。请帮忙,我错过了什么案例?

Mar*_*ell 5

这里有一个线程竞赛,其中另一个任务正在尝试获取相同的信号量,并在您Release(即另一个线程正在等待semaphore.WaitAsync(). 检查CurrentCount是一种竞争条件,根据时间的不同,它可能会发生任何一种情况。检查TryRemove是无关紧要的,因为竞争线程已经获取了信号量 - 毕竟它正在等待WaitAsync().