C#线程池限制线程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/444627/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 03:36:50  来源:igfitidea点击:

C# thread pool limiting threads

c#multithreadingc#-2.0threadpool

提问by jason baisden

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.

好吧...我已经对网站进行了公平的搜索,并阅读了许多关于此主题的帖子。我发现这个问题:Code for a simple thread pool in 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. The example I refer to is here: http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80,printer).aspx

我查看了 MSDN 示例并根据我的需要对其进行了一些调整。我参考的例子在这里: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 HttpWebRequestand WebResponseclasses and reads the results via a 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.

我的问题是这个。我有一组相当简单的代码,它通过HttpWebRequestWebResponse类加载网页并通过Stream. 我在一个线程中触发这个方法,因为它需要执行多次。该方法本身很短,但需要触发的次数(每次都有不同的数据)各不相同。它可以是 1 到 200 之间的任何值。

Everything I've read seems to indicate the ThreadPoolclass being the prime candidate. 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).

我读过的所有内容似乎都表明该ThreadPool班级是主要候选人。这就是事情变得棘手的地方。我可能需要将这个东西发射 100 次,但我最多只能运行 3 个线程(对于这个特定任务)。

I've tried setting the MaxThreadson the ThreadPoolvia:

我试过MaxThreadsThreadPoolvia上设置:

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,我可以确定这仅与我的代码和线程有关吗?

The MSDN example uses the event drive approach and calls WaitHandle.WaitAll(doneEvents);which is how I'm doing this.

MSDN 示例使用事件驱动方法和调用WaitHandle.WaitAll(doneEvents);,这就是我这样做的方式。

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 ThreadPoolcode. It seems simple enough. I got my info from: http://www.albahari.com/threading/part2.aspx

好的,我已经添加了一个信号量方法并完全删除了ThreadPool代码。这似乎很简单。我的信息来自: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 Semaphorewith a capacity of one is similar to a Mutexor lock, except that the Semaphorehas no "owner" – it's thread-agnostic. Any thread can call Releaseon a Semaphore, while with Mutexand lock, only the thread that obtained the resource can release it.

Semaphore容量为 1 的A类似于 a Mutexor lock,不同之处在于Semaphore没有“所有者”——它与线程无关。任何线程都可以调用Releasea Semaphore,而使用Mutexlock,只有获得资源的线程才能释放它。

In this following example, ten threads execute a loop with a Sleepstatement in the middle. A Semaphoreensures that not more than three threads can execute that Sleepstatement at once:

在以下示例中,十个线程执行一个循环,Sleep中间有一个语句。ASemaphore确保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();
        }
    }
}

采纳答案by Michael Haren

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. 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!

注意:如果您将其限制为“3”只是为了不让运行您的应用程序的机器不堪重负,我会首先确保这是一个问题。线程池应该为你管理这个。另一方面,如果您不想淹没其他资源,请继续阅读!



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.

在这种情况下,我会使用信号量来管理对资源的访问。在您的情况下,您的资源正在运行网络抓取,或计算一些报告等。

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. Once S has been decremented 3 times, all threads will block until one of them increments the counter.

每个线程都将阻塞在 S.WaitOne() 上,直到它收到继续进行的信号为止。一旦 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 方法,在这种方法中,您将要执行的工作排入全局 Blocking Queue 对象中。

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:

例子:

回答by jalf

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. 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 ourtask, without having it interfere with unrelated tasks elsewhere in the system.

然而,我认为这是 .NET 中较大的设计缺陷之一。谁想出了使线程池静态化的绝妙主意?如您的示例所示,我们通常需要一个专用于我们的任务的线程池,而不会干扰系统中其他地方的无关任务。