简体   繁体   English

C#线程池限制线程

[英]C# thread pool limiting threads

Alright...I've given the site a fair search and have read over many posts about this topic. 好吧......我给了网站一个公平的搜索,并阅读了很多关于这个主题的帖子。 I found this question: Code for a simple thread pool in C# especially helpful. 我发现了这个问题: C#中一个简单线程池的代码特别有用。

However, as it always seems, what I need varies slightly. 但是,总是看起来,我需要的东西略有不同。

I have looked over the MSDN example and adapted it to my needs somewhat. 我查看了MSDN示例,并根据我的需要进行了调整。 The example I refer to is here: http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80,printer).aspx 我引用的示例如下: http//msdn.microsoft.com/en-us/library/3dasc8as(VS.80,printer).aspx

My issue is this. 我的问题是这个。 I have a fairly simple set of code that loads a web page via the HttpWebRequest and WebResponse classes and reads the results via a Stream . 我有一组相当简单的代码,它通过HttpWebRequestWebResponse类加载网页,并通过Stream读取结果。 I fire off this method in a thread as it will need to executed many times. 我在一个线程中触发此方法,因为它需要执行多次。 The method itself is pretty short, but the number of times it needs to be fired (with varied data for each time) varies. 该方法本身很短,但需要触发的次数(每次都有不同的数据)会有所不同。 It can be anywhere from 1 to 200. 它可以是1到200之间的任何地方。

Everything I've read seems to indicate the ThreadPool class being the prime candidate. 我读过的所有内容似乎都表明ThreadPool类是主要的候选者。 Here is what things get tricky. 这就是事情变得棘手的事情。 I might need to fire off this thing say 100 times, but I can only have 3 threads at most running (for this particular task). 我可能需要发出100次这样的事情,但我最多只能运行3个线程(对于这个特定的任务)。

I've tried setting the MaxThreads on the ThreadPool via: 我已尝试通过以下方式在ThreadPool上设置MaxThreads

ThreadPool.SetMaxThreads(3, 3);

I'm not entirely convinced this approach is working. 我并不完全相信这种方法有效。 Furthermore, I don't want to clobber other web sites or programs running on the system this will be running on. 此外,我不想破坏将在其上运行的系统上运行的其他网站或程序。 So, by limiting the # of threads on the ThreadPool , can I be certain that this pertains to my code and my threads only? 因此,通过限制ThreadPool上的ThreadPool ,我可以确定这只与我的代码和我的线程有关吗?

The MSDN example uses the event drive approach and calls WaitHandle.WaitAll(doneEvents); MSDN示例使用事件驱动器方法并调用WaitHandle.WaitAll(doneEvents); which is how I'm doing this. 这就是我这样做的方式。

So the heart of my question is, how does one ensure or specify a maximum number of threads that can be run for their code, but have the code keep running more threads as the previous ones finish up until some arbitrary point? 所以我的问题的核心是,如何确保或指定可以为其代码运行的最大线程数,但让代码继续运行更多线程,因为之前的线程完成直到任意点? Am I tackling this the right way? 我是以正确的方式解决这个问题吗?

Sincerely, 此致

Jason 贾森


Okay, I've added a semaphore approach and completely removed the ThreadPool code. 好的,我添加了一个信号量方法并完全删除了ThreadPool代码。 It seems simple enough. 看起来很简单。 I got my info from: http://www.albahari.com/threading/part2.aspx 我从http://www.albahari.com/threading/part2.aspx获取了我的信息

It's this example that showed me how: 这个例子向我展示了如何:

[text below here is a copy/paste from the site] [此处的文字是网站的复制/粘贴]

A Semaphore with a capacity of one is similar to a Mutex or lock , except that the Semaphore has no "owner" – it's thread-agnostic. 容量为1的Semaphore类似于Mutexlock ,除了Semaphore没有“所有者” - 它与线程无关。 Any thread can call Release on a Semaphore , while with Mutex and lock , only the thread that obtained the resource can release it. 任何线程都可以在Semaphore上调用Release ,而使用Mutexlock ,只有获得资源的线程才能释放它。

In this following example, ten threads execute a loop with a Sleep statement in the middle. 在下面的示例中,十个线程在中间执行一个带有Sleep语句的循环。 A Semaphore ensures that not more than three threads can execute that Sleep statement at once: 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();
        }
    }
}

Note: if you are limiting this to "3" just so you don't overwhelm the machine running your app, I'd make sure this is a problem first. 注意:如果您将此限制为“3”只是为了不让运行应用程序的机器淹没,我首先要确保这是一个问题。 The threadpool is supposed to manage this for you. 线程池应该为你管理这个。 On the other hand, if you don't want to overwhelm some other resource, then read on! 另一方面,如果你不想压倒其他一些资源,请继续阅读!


You can't manage the size of the threadpool (or really much of anything about it). 您无法管理线程池的大小(或者实际上关于它的任何内容)。

In this case, I'd use a semaphore to manage access to your resource. 在这种情况下,我将使用信号量来管理对资源的访问。 In your case, your resource is running the web scrape, or calculating some report, etc. 在您的情况下,您的资源正在运行Web scrape,或计算某些报告等。

To do this, in your static class, create a semaphore object: 为此,在静态类中,创建一个信号量对象:

System.Threading.Semaphore S = new System.Threading.Semaphore(3, 3);

Then, in each thread, you do this: 然后,在每个线程中,您执行此操作:

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();
}

Each thread will block on the S.WaitOne() until it is given the signal to proceed. 每个线程将在S.WaitOne()上阻塞,直到给出信号继续。 Once S has been decremented 3 times, all threads will block until one of them increments the counter. 一旦S减少了3次,所有线程都会阻塞,直到其中一个增加计数器。

This solution isn't perfect. 这个解决方案并不完美。


If you want something a little cleaner, and more efficient, I'd recommend going with a BlockingQueue approach wherein you enqueue the work you want performed into a global Blocking Queue object. 如果您想要更清洁,更高效的东西,我建议您使用BlockingQueue方法,其中您将要执行的工作排入全局阻塞队列对象。

Meanwhile, you have three threads (which you created--not in the threadpool), popping work out of the queue to perform. 同时,你有三个线程(你创建的 - 不在线程池中),弹出队列中的工作来执行。 This isn't that tricky to setup and is very fast and simple. 这不是那么棘手的设置,而且非常快速和简单。

Examples: 例子:

It's a static class like any other, which means that anything you do with it affects every other thread in the current process. 它与任何其他类似的静态类,这意味着您使用它做的任何事情都会影响当前进程中的每个其他线程。 It doesn't affect other processes. 它不会影响其他进程。

I consider this one of the larger design flaws in .NET, however. 不过,我认为这是.NET中较大的设计缺陷之一。 Who came up with the brilliant idea of making the thread pool static ? 谁提出了使线程池静态的好主意? As your example shows, we often want a thread pool dedicated to our task, without having it interfere with unrelated tasks elsewhere in the system. 正如您的示例所示,我们经常需要专用于我们任务的线程池,而不会干扰系统中其他位置的无关任务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM