目录
介绍
背景
使用代码
兴趣点
- 下载源代码19.5 KB
当控制活动任务/线程的数量时,Semaphore和SemaphoreSlim是有用且有价值的组件。但是,现有的Semaphore和SemaphoreSlim实现不允许实例化后重新调整信号量的大小——因此,无法通过调整实例化信号量的大小来限制任务/线程。
背景使用信号量作为限制或限制应用程序的方法是一种众所周知的方法,但是——在.NET世界中,无法通过某种方式调整实例化的信号量或SemaphoreSlim的大小,从而允许对要进行的节流进行调整。
在Java中,AdjustableSemaphore中已经存在了一段时间——在着眼于实现.NET时,我遇到了一系列讨论这一确切要求的帖子:
- 如何实现动态信号量?
调整一些小的功能更改,以允许初始化大小为0(zero)的AdjustableSemaphore,进行一些命名和声明更新,以及满足我的需求的全功能的AdjustableSemaphore。
使用代码AdjustableSemaphore本身是一个很简单的类:
using System;
using System.Threading;
namespace CPSemaphore
{
///
/// Implementation of an AdjustableSemaphore - similar to that provided
/// in the Java namesake, allowing for the Semaphore to be resizeddynamically
/// https://github.com/addthis/basis/blob/master/basis-core/src/main/java/com/
/// addthis/basis/util/AdjustableSemaphore.java
/// .NET version originally published at the following URL
/// https://social.msdn.microsoft.com/Forums/vstudio/en-US/
/// 5b648588-298b-452e-bc9a-1df0258242fe/
/// how-to-implement-a-dynamic-semaphore?forum=netfxbcl
/// Minor alterations made, allowing for initialization using 0 as Semaphore size,
/// syntax and naming convention changes
///
public class AdjustableSemaphore
{
private static readonly object m_LockObject = new object();
private int m_AvailableCount = 0;
private int m_MaximumCount = 0;
public AdjustableSemaphore(int maximumCount)
{
MaximumCount = maximumCount;
}
public int MaximumCount
{
get
{
lock (m_LockObject)
{
return m_MaximumCount;
}
}
set
{
lock (m_LockObject)
{
if (value < 0)
{
throw new ArgumentException("Must be greater than or equal to 0.",
"MaximumCount");
}
m_AvailableCount += value - m_MaximumCount; // m_AvailableCount
// can be < 0, resize will not affect active semaphores
m_MaximumCount = value;
Monitor.PulseAll(m_LockObject);
}
}
}
public void WaitOne()
{
lock (m_LockObject)
{
while (m_AvailableCount
{
Random rnd = new Random();
semaphoreObject.WaitOne();
semaphoreObject.GetSemaphoreInfo(out int maxCount,
out int usedCount, out int availableCount);
Console.WriteLine("{0} - Acquired Semaphore - Semaphore Max: {1},
Used: {2}, Available: {3}", j, maxCount, usedCount, availableCount);
Thread.Sleep(rnd.Next(1000, 5000));
semaphoreObject.Release();
semaphoreObject.GetSemaphoreInfo(out maxCount, out usedCount,
out availableCount);
Console.WriteLine("{0} - Released Semaphore - Semaphore Max: {1},
Used: {2}, Available: {3}", j, maxCount, usedCount, availableCount);
}));
}
semaphoreObject.MaximumCount = 6;
Console.WriteLine("Awaiting All Tasks");
Thread.Sleep(1000);
semaphoreObject.MaximumCount = 3;
Task.WaitAll(tasks.ToArray());
Console.WriteLine("All Tasks Complete");
Console.ReadLine();
}
}
}
运行的输出将类似于以下内容:
Awaiting All Tasks
6 - Aquired Semaphore - Semaphore Max: 6, Used: 6, Available: 0
5 - Aquired Semaphore - Semaphore Max: 6, Used: 6, Available: 0
1 - Aquired Semaphore - Semaphore Max: 6, Used: 6, Available: 0
4 - Aquired Semaphore - Semaphore Max: 6, Used: 6, Available: 0
3 - Aquired Semaphore - Semaphore Max: 6, Used: 6, Available: 0
7 - Aquired Semaphore - Semaphore Max: 6, Used: 6, Available: 0
3 - Released Semaphore - Semaphore Max: 3, Used: 5, Available: -2
1 - Released Semaphore - Semaphore Max: 3, Used: 4, Available: -1
7 - Released Semaphore - Semaphore Max: 3, Used: 3, Available: 0
4 - Released Semaphore - Semaphore Max: 3, Used: 2, Available: 1
9 - Aquired Semaphore - Semaphore Max: 3, Used: 3, Available: 0
5 - Released Semaphore - Semaphore Max: 3, Used: 1, Available: 2
6 - Released Semaphore - Semaphore Max: 3, Used: 2, Available: 1
8 - Aquired Semaphore - Semaphore Max: 3, Used: 2, Available: 1
2 - Aquired Semaphore - Semaphore Max: 3, Used: 3, Available: 0
9 - Released Semaphore - Semaphore Max: 3, Used: 2, Available: 1
0 - Aquired Semaphore - Semaphore Max: 3, Used: 3, Available: 0
2 - Released Semaphore - Semaphore Max: 3, Used: 2, Available: 1
8 - Released Semaphore - Semaphore Max: 3, Used: 1, Available: 2
0 - Released Semaphore - Semaphore Max: 3, Used: 0, Available: 3
All Tasks Complete
从样本输出中可以看出,将AdjustableSemaphore从6调整为3会导致负数的信号量可用,直到完成并释放第三个任务(数字7)为止,此时可用计数为0。
任务四(数字4)完成后,可用计数为1,然后运行新任务(数字9)。
兴趣点AdjustableSemaphore将允许你通过动态地调整AdjustableSemaphore来调节处理,并且它在过去当我不得不实现动态的缩放过程时很方便。