信号量动态调整大小 C#
我试图使用信号量来控制可以同时运行的作业实例的数量。虽然这对于等待方法来说相当简单,但我还希望该值可以在运行时配置,以便我可以向上或向下增加计数。
我意识到倒计时可能会出现问题,但有没有办法真正做到这一点?这是使用信号量的正确方法吗?
I'm trying to use semaphores to control how many instances of a job can be run at the same time. While this is fairly simple with a wait method, I also want the value to be configurable at runtime so that I can bump the count up or down.
I realize that there may be issues bumping the count down but is there a way to actually do this? Is this the right approach to be using semaphores?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
根据 ReleaseSemaphore 的文档,对于
lReleaseCount
参数:这和其他文档表明信号量对于您的限制来说不是正确的选择。信号量一旦创建,就会有一个硬性最大值,如果不重新创建信号量就无法更改该最大值。换句话说,它不是一个可以更改的动态值。
在这种情况下,您需要找到另一种方法来管理您的限制。
使用信号量的一种方法是分配一个足够大的信号量来满足所有未来的需求,然后获取足够的“实例”以减少可用的信号量数量回到您目前需要的数量。当您想要增加可用实例的数量时,只需释放您一开始就获取的一些实例即可。
但是,我质疑你为什么要这样做。真正决定你可以同时执行多少个作业的限制因素是什么?信号量很可能不是这个问题的正确答案。
According to the documentation of ReleaseSemaphore, for the
lReleaseCount
parameter:This, and other documentation suggests that a semaphore is not the right choice for your limitation. A semaphore, once created, has a hard maximum that cannot be changed without recreating the semaphore. In other words, it is not a dynamic value that can be changed.
You need to find another way of managing your limit in this scenario.
One way you could use a semaphore would be to allocate a semaphore that is big enough for all future needs, and then just grab enough "instances" of it to reduce the available number back down to what you need at the moment. When you want to increase the number of available instances, just release some of those you grabbed at the beginning.
However, I question why you want to do this. What is the limiting factor that really decides how many jobs you can execute at the same time here? Most likely a semaphore is not the right answer to this.
我不建议为此使用信号量。
如果您使用 .NET 4,我建议的方法是创建一个自定义 TaskScheduler 允许您在运行时更改并发级别。然后,您可以使用在选项中传递此 TaskScheduler 的单个
Parallel.For
/ForEach
调用来运行整个操作,并在运行时更改并发级别。这将使处理向上或向下移动级别变得相当容易。当级别上升时,您只需根据需要添加新线程即可。当它们出现故障时,只需从内部集合中删除该线程(但不要停止它),并让它完成当前的工作。这将允许您根据需要进行扩展。
I would not recommend using semaphores for this.
If you're in .NET 4, my suggested method would be to create a custom TaskScheduler which would allow you to change the level of concurrency at runtime. You could then run your entire operation using a single
Parallel.For
/ForEach
call passing this TaskScheduler in the options, and change the level of concurrency at runtime.This would make it fairly easy to handle moving levels up or down. When levels go up, you just add new threads as needed. When they go down, just remove that thread from your internal collection (but don't stop it), and let it finish its current work. This would allow you to scale as needed.
根据Lasse V. Karlsen的建议,我在kotlin中实现了一个动态信号量。我不知道如何在 C# 中做到这一点,但应该相当相似。只需将其视为伪代码答案即可。
该代码具有以下行为:
您可以创建信号量,如果您从不更新它,它将完全像信号量一样工作
增加许可证将释放许可证最多 100 个(随意增加最大值)
当仍有大量许可证时减少许可证是即时的
当当前发放的许可证多于新的允许限制时减少许可证最终将减少许可证,从而允许进程自行完成。在达到目标许可证之前不会发放新许可证
Based on the suggestion of Lasse V. Karlsen I implemented a dynamic semaphore in kotlin. I do not know how to do it in C#, but should be fairly similar. Just consider this a pseudo code answer.
The code has the following behaviour:
you can create the semphaphore and it will act exactly like a semamphore if you never update it
increasing the permits will release permits up to 100 (feel free to increase the maximum)
decreasing the permits when there are still plenty permits left is instant
decreasing the permits when there are more currently handed out the permits than the new allowed limit will eventually decrease the permits allowing processes to finish on their own. New permits are not handed out until the target permits have been reached