【问题标题】:SemaphoreSlim not spinning up to maximum number of threadsSemaphoreSlim 没有达到最大线程数
【发布时间】:2019-10-02 00:48:43
【问题描述】:

我以为我了解 SemaphoreSlim,但我想我需要一些帮助。如果我声明一个 maxCount 为 2 的信号量,那么我假设在循环内每次调用 WaitAsync() 时,信号量计数最多会增长到 2,最多允许一次运行两个任务,但它只运行即使我在每个任务结束时释放信号量,也一次一个。有人能解释一下为什么这段代码一次运行一个任务吗?

class Program
{
    static SemaphoreSlim _loopThrottle = new SemaphoreSlim(1, 2);

    static async Task Main(string[] args)
    {
        for (int taskID = 1; taskID <= 10; taskID++)
        {
            await _loopThrottle.WaitAsync();
            var t = SomeFunctionAsync(taskID);
        }
        Console.ReadLine();
    }

    private async static Task SomeFunctionAsync(int taskID)
    {
        await Task.Delay(1000);
        Console.WriteLine(taskID);
        _loopThrottle.Release();
    }
}

【问题讨论】:

    标签: multithreading .net-core task semaphore


    【解决方案1】:

    您误解了 SemaphoreSlim 构造函数参数,initialCount 应该为 2。您声称两个可用“插槽”之一不可用(您的 .CurrentCount 开头将是 1)。因为只剩下一个请求,所以您的循环不能以一次高于一个的速率触发 SomeFunctionAsync() 任务。因为这些中的每一个都只有一次 Release(),所以您永远不会释放您声明为 maxCount 的两个插槽。

    【讨论】:

    • 对于这种场景,你可以只使用单参数构造函数new SemaphoreSlim(2)
    • 这就是我所看到的。如果构造函数的第一个值始终控制允许的最大线程数,那么为什么要实际指定最大计数的第二个值呢?仍然必须缺少一些简单的东西。
    • 关于声明其中一个可用点,我将参数更改为 1 和 5,它仍然一次只处理一个。静态 SemaphoreSlim _loopThrottle = new SemaphoreSlim(1, 5);
    • 通过指定 (1,5),您声称最多可以授予五个,但目前只有一个可用,这就是您看到这种一次一个行为的原因.每个任务都被前一个任务阻止,它只释放一个点。用 (5,5) 试试,它会按预期工作。
    • 也许我需要换个方式问这个问题。如果我使用带有两个值(初始值和最大值)(5,5)的第二个构造函数,用单个值 5 声明信号量似乎表现相同。他们必须有两个构造函数的原因吗?从逻辑上讲,我看到了两者的原因。 “我可能会发生多达 5 件事,但我可能不会只使用你需要的数量”,这将是 1、5 组参数。或者我总是一次运行 5 件事情,所以请继续将它们预先声明为 5、5)。
    猜你喜欢
    • 2013-04-17
    • 1970-01-01
    • 2011-04-20
    • 2016-09-14
    • 1970-01-01
    • 2023-03-15
    • 2020-11-02
    • 2011-10-05
    相关资源
    最近更新 更多