[英]C# thread pool limiting threads
好吧......我给了网站一个公平的搜索,并阅读了很多关于这个主题的帖子。 我发现了这个问题: 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”只是为了不让运行应用程序的机器淹没,我首先要确保这是一个问题。 线程池应该为你管理这个。 另一方面,如果你不想压倒其他一些资源,请继续阅读!
您无法管理线程池的大小(或者实际上关于它的任何内容)。
在这种情况下,我将使用信号量来管理对资源的访问。 在您的情况下,您的资源正在运行Web scrape,或计算某些报告等。
为此,在静态类中,创建一个信号量对象:
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减少了3次,所有线程都会阻塞,直到其中一个增加计数器。
这个解决方案并不完美。
如果您想要更清洁,更高效的东西,我建议您使用BlockingQueue方法,其中您将要执行的工作排入全局阻塞队列对象。
同时,你有三个线程(你创建的 - 不在线程池中),弹出队列中的工作来执行。 这不是那么棘手的设置,而且非常快速和简单。
例子:
它与任何其他类似的静态类,这意味着您使用它做的任何事情都会影响当前进程中的每个其他线程。 它不会影响其他进程。
不过,我认为这是.NET中较大的设计缺陷之一。 谁提出了使线程池静态的好主意? 正如您的示例所示,我们经常需要专用于我们任务的线程池,而不会干扰系统中其他位置的无关任务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.