我遇到了一个问题,我需要限制到另一个Web服务器的调用数量。这将有所不同,因为服务器是共享的,并且可能具有更多或更少的容量。

我当时正在考虑使用SemaphoreSlim类,但是没有公共(public)属性可以更改最大计数。

我应该将SemaphoreSlim类包装在另一个可以处理最大计数的类中吗?有没有更好的办法?

编辑:

这是我正在尝试的方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Semaphore
{
class Program
{
    static SemaphoreSlim _sem = new SemaphoreSlim(10,10000);

    static void Main(string[] args)
    {
        int max = 15;

        for (int i = 1; i <= 50; i++)
        {
            new Thread(Enter).Start(new int[] { i, max});
        }

        Console.ReadLine();

        max = 11;

        for (int i = 1; i <= 50; i++)
        {
            new Thread(Enter).Start(new int[] { i, max });
        }
    }

    static void Enter(object param)
    {
        int[] arr = (int[])param;
        int id = arr[0];
        int max = arr[1];

        try
        {
            Console.WriteLine(_sem.CurrentCount);

            if (_sem.CurrentCount <= max)
                _sem.Release(1);
            else
            {
                _sem.Wait(1000);

                Console.WriteLine(id + " wants to enter");

                Thread.Sleep((1000 * id) / 2); // can be here at

                Console.WriteLine(id + " is in!"); // Only three threads

            }
        }
        catch(Exception ex)
        {
            Console.WriteLine("opps ", id);
            Console.WriteLine(ex.Message);
        }
        finally
        {
            _sem.Release();
        }
    }
}
}

问题:

1-_sem.Wait(1000)应该取消将执行1000ms以上的线程的执行,不是吗?

2-我是否有使用Release/Wait的想法?

最佳答案

您不能更改最大计数,但是可以创建一个具有非常高的最大计数的SemaphoreSlim,并保留其中的一些。参见this constructor

因此,假设并发调用的绝对最大数量为100,但最初希望将其设置为25。您可以初始化信号量:

SemaphoreSlim sem = new SemaphoreSlim(25, 100);

因此,可以同时处理的请求数为25。您已保留其他75个。

如果然后要增加允许的数量,只需调用Release(num)即可。如果您调用Release(10),那么该数字将达到35。

现在,如果要减少可用请求的数量,则必须多次调用WaitOne。例如,如果要从可用计数中删除10:
for (var i = 0; i < 10; ++i)
{
    sem.WaitOne();
}

这有可能会阻塞,直到其他客户端释放信号量为止。也就是说,如果您允许35个并发请求,并且希望将其减少到25个,但是已经有35个具有事件请求的客户端,则WaitOne将阻塞,直到一个客户端调用Release为止,直到10个客户端释放,循环才会终止。

10-04 11:38