问题:有多个线程访问资源。我需要限制他们的号码为一个常数MaxThreads
。无法进入线程池的线程应该会收到错误消息。线程池与BlockingCollection
解决方案:我开始使用下面的算法BlockingCollection<string> pool
,但我看到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());
}
关于如何更好地实现这一点的任何想法?
谢谢!
P.S.多线程新手在这里,如果你有任何阅读材料的建议,我会非常感激他们。
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());
}
考虑使用[semaphore](http://msdn.microsoft.com/en-us/library/system.threading.semaphore(v = vs.110).aspx)。信号量就像一个酒吧保镖。他允许一定数量的人进出。如果里面的人比酒吧可以处理的人多,他不会允许任何人进入,除非有人离开。您可以使用'WaitOne'重载等待指定时间,然后才会出现超时异常 – oleksii 2014-09-29 12:11:25