您当前的位置: 首页 >  .net

寒冰屋

暂无认证

  • 0浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

.NET的可调信号量

寒冰屋 发布时间:2020-07-10 20:58:19 ,浏览量:0

目录

介绍

背景

使用代码

兴趣点

  • 下载源代码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来调节处理,并且它在过去当我不得不实现动态的缩放过程时很方便。

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.1003s