C# 具有BlockingCollection的线程池

C# 具有BlockingCollection的线程池,c#,multithreading,blockingqueue,blockingcollection,C#,Multithreading,Blockingqueue,Blockingcollection,问题:有多个线程正在访问一个资源。我需要将它们的数量限制为常量MaxThreads。无法进入线程池的线程将收到错误消息 解决方案:我开始在下面的算法中使用BlockingCollection池,但我发现BlockingCollection需要调用completedadding,这是我无法做到的,因为我总是得到传入线程(为了调试目的,我在下面的示例中硬编码为10),考虑web请求 public class MyTest { private const int MaxThreads = 3

问题:有多个线程正在访问一个资源。我需要将它们的数量限制为常量
MaxThreads
。无法进入线程池的线程将收到错误消息

解决方案:我开始在下面的算法中使用
BlockingCollection池
,但我发现
BlockingCollection
需要调用
completedadding
,这是我无法做到的,因为我总是得到传入线程(为了调试目的,我在下面的示例中硬编码为10),考虑web请求

public class MyTest {

    private const int MaxThreads = 3;

    private BlockingCollection<string> pool;

    public MyTest() { 
        pool = new BlockingCollection<string>(MaxThreads);
    }

    public void Go() {
        var addSuccess = this.pool.TryAdd(string.Format("thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        if (!addSuccess) Console.WriteLine(string.Format("thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        Console.WriteLine(string.Format("Adding thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        Console.WriteLine(string.Format("Pool size: {0}", pool.Count));

        // simulate work
        Thread.Sleep(1000);

        Console.WriteLine("Thread ID#{0} " + Thread.CurrentThread.ManagedThreadId + " is done doing work.");
        string val;
        var takeSuccess = this.pool.TryTake(out val);
        if (!takeSuccess) Console.WriteLine(string.Format("Failed to take out thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        Console.WriteLine("Taking out " + val);

        Console.WriteLine(string.Format("Pool size: {0}", pool.Count));
        Console.WriteLine(Environment.NewLine);
    }
}

static void Main()
{
    var t = new MyTest();

    Parallel.For(0, 10, x => t.Go());
}

如果您想保护一定数量的线程,这些线程一次可以访问一个关键区域,则必须使用或。我建议后一种,与前一种相比重量轻

SemaphoreSlim
的一个缺点是它们不会跨进程工作,但这很好,我们有
Semaphore
来提供帮助

您可以通过框架提供的带有超时的等待方法之一来测试信号量是否已满

SemaphoreSlim semaphore = new SemaphoreSlim(3, 3);

if (!semaphore.Wait(0))
{
    //Already semaphore full.
    //Handle it as you like
}

是一个非常好的线程资源。

如果您想保护一定数量的线程,这些线程一次可以访问一个关键区域,则必须使用或。我建议后一种,与前一种相比重量轻

SemaphoreSlim
的一个缺点是它们不会跨进程工作,但这很好,我们有
Semaphore
来提供帮助

您可以通过框架提供的带有超时的等待方法之一来测试信号量是否已满

SemaphoreSlim semaphore = new SemaphoreSlim(3, 3);

if (!semaphore.Wait(0))
{
    //Already semaphore full.
    //Handle it as you like
}
是非常好的线程资源。

请考虑使用。信号灯就像酒吧保镖。他允许一定数量的人进出。如果酒吧里的人太多了,他不会允许任何人进来,除非有人离开。您可以使用
WaitOne
重载等待指定时间,然后使用。信号灯就像酒吧保镖。他允许一定数量的人进出。如果酒吧里的人太多了,他不会允许任何人进来,除非有人离开。您可以使用
WaitOne
重载等待指定时间,然后才能获得超时异常