C#线程池限制线程
好的…我已经给了这个网站一个公平的search,并且阅读了很多关于这个主题的文章。 我发现这个问题: 在C#中的简单线程池代码特别有用。
不过,就像看起来一样,我需要的东西稍有不同。
我已经看了MSDN的例子,并适应了我的需求。 我提到的例子是在这里: http : //msdn.microsoft.com/en-us/library/3dasc8as(VS.80,printer).aspx
我的问题是这个。 我有一个相当简单的代码集,通过HttpWebRequest
和WebResponse
类加载网页,并通过Stream
读取结果。 我在线程中引发这个方法,因为它需要执行很多次。 该方法本身很短,但它需要被触发的次数(每次不同的数据)是不同的。 它可以是从1到200的任何地方。
我读过的所有东西似乎都表明ThreadPool
类是主要的候选者。 这是棘手的事情。 我可能需要说这个东西说100次,但我最多只能有3个线程运行(为这个特定的任务)。
我已经尝试通过设置ThreadPool
上的MaxThreads
:
ThreadPool.SetMaxThreads(3, 3);
我不完全相信这种方法正在工作。 此外,我不想闯入系统上运行的其他网站或程序,这将运行。 所以,通过限制ThreadPool
上的ThreadPool
,我可以确定这只适用于我的代码和我的线程吗?
MSDN示例使用事件驱动方法并调用WaitHandle.WaitAll(doneEvents);
这是我如何做到这一点。
所以我的问题的核心是,如何确保或指定可以为其代码运行的线程的最大数量,但代码继续运行更多的线程,因为以前的完成,直到任意点? 我正确的解决这个问题吗?
此致
贾森
好吧,我已经添加了一个信号量方法,并完全删除了ThreadPool
代码。 这似乎很简单。 我从我的信息: http : //www.albahari.com/threading/part2.aspx
这个例子向我展示了如何:
[下面的文本是从网站复制/粘贴]
一个容量为1的Semaphore
与一个Mutex
或lock
相似,只是Semaphore
没有“所有者” – 它是线程无关的。 任何线程都可以在Semaphore
上调用Release
,而在使用Mutex
和lock
,只有获取资源的线程才能释放它。
在下面的例子中,十个线程在中间执行一个Sleep
语句的循环。 Semaphore
确保一次不超过三个线程可以执行该Sleep
语句:
class SemaphoreTest { static Semaphore s = new Semaphore(3, 3); // Available=3; Capacity=3 static void Main() { for (int i = 0; i < 10; i++) new Thread(Go).Start(); } static void Go() { while (true) { s.WaitOne(); Thread.Sleep(100); // Only 3 threads can get here at once s.Release(); } } }
注意:如果你限制这个“3”,所以你不要压倒运行你的应用程序的机器,我会确保这是第一个问题。 线程池应该为你pipe理这个。 另一方面,如果你不想压倒一些其他资源,然后阅读!
你不能pipe理线程池的大小(或者关于它的任何事情)。
在这种情况下,我会使用信号量来pipe理对资源的访问。 在你的情况,你的资源正在运行networking刮,或计算一些报告等。
为此,在静态类中创build一个信号量对象:
System.Threading.Semaphore S = new System.Threading.Semaphore(3, 3);
然后,在每个线程中,你这样做:
System.Threading.Semaphore S = new System.Threading.Semaphore(3, 3); try { // wait your turn (decrement) S.WaitOne(); // do your thing } finally { // release so others can go (increment) S.Release(); }
每个线程都会阻塞在S.WaitOne()上,直到给出信号继续。 一旦S减less了3次,所有的线程都将被阻塞,直到其中一个线程递增计数器。
这个解决scheme并不完美。
如果你想要一些更干净,更高效的东西,我build议你用一个BlockingQueue方法,把你想要执行的工作排入一个全局的Blocking Queue对象。
同时,你有三个线程(你创build的 – 不在线程池中),popup队列执行。 这不是很难安装,是非常快速和简单。
例子:
- 最好的线程队列示例/最佳实践
- 在并发程序中从BlockingQueue获取对象的最佳方法?
这是一个类似于任何其他的静态类,这意味着你使用它的任何事情都会影响当前进程中的其他线程。 它不影响其他进程。
但是,我认为这是.NET中较大的devise缺陷之一。 谁想出了使线程池静态的好主意? 如你的例子所示,我们经常需要一个专用于我们任务的线程池,而不会干扰系统中其他地方不相关的任务。