具有BlockingCollection的线程池

mo5*_*470 1 c# multithreading blockingqueue blockingcollection

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

解决方案:我开始BlockingCollection<string> pool在下面的算法中使用a ,但是我看到BlockingCollection需要调用CompleteAdding,我不能这样做,因为我总是得到传入的线程(我在下面的示例中硬编码为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());
}
Run Code Online (Sandbox Code Playgroud)

关于如何更好地实现这一目标的任何想法?

谢谢!

PS多线程新手在这里,如果您对阅读材料有任何建议,我将非常感谢他们.

LE:基于我得到的答案,我能够使用此算法实现所需的行为:

public class MyTest {

    private const int MaxThreads = 3;

    private SemaphoreSlim semaphore;

    public MyTest() { 
        semaphore = new SemaphoreSlim(MaxThreads, MaxThreads);
    }

    public void Go() {

        Console.WriteLine(string.Format("In comes thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        semaphore.Wait();

        try {

        Console.WriteLine(string.Format("Serving thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        // simulate work
        Thread.Sleep(1000);
        Console.WriteLine(string.Format("Out goes thread ID#{0}", Thread.CurrentThread.ManagedThreadId));

        }

        finally {
            semaphore.Release();
        }

    }
}

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

    Parallel.For(0, 10, x=> t.Go());
}
Run Code Online (Sandbox Code Playgroud)

Sri*_*vel 5

如果要保护一次可以访问关键区域的特定数量的线程,则必须使用SemaphoreSemaphoreSlim.我建议使用后者,与前者相比重量轻.

一个缺点SemaphoreSlim是它们不会在交叉过程中工作,但我们必须Semaphore提供帮助.

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

SemaphoreSlim semaphore = new SemaphoreSlim(3, 3);

if (!semaphore.Wait(0))
{
    //Already semaphore full.
    //Handle it as you like
}
Run Code Online (Sandbox Code Playgroud)

http://www.albahari.com/threading/是一个非常好的线程资源.