首页 文章

C#线程池限制线程

提问于
浏览
36

好吧......我给了网站一个公平的搜索,并阅读了很多关于这个主题的帖子 . 我发现了这个问题:Code for a simple thread pool in C#特别有帮助 .

但是,总是看起来,我需要的东西略有不同 .

我查看了MSDN示例,并根据我的需要进行了调整 . 我所指的例子是:http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80,printer).aspx

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

我读过的所有内容似乎都表明 ThreadPool 课程是主要候选人 . 这是件事变得棘手的事情 . 我可能需要发出100次这样的事情,但我最多只能运行3个线程(对于这个特定的任务) .

我已经尝试在 ThreadPool 上设置 MaxThreads

ThreadPool.SetMaxThreads(3, 3);

我想要破坏将在其上运行的系统上运行的其他网站或程序 . 因此,通过限制 ThreadPool 上的线程数,我可以确定这仅适用于我的代码和我的线程吗?

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

所以我的问题的核心是,如何确保或指定可以为其代码运行的最大线程数,但让代码继续运行更多线程,因为之前的线程完成直到任意点?我是以正确的方式解决这个问题吗?

此致

贾森


好的,我添加了一个信号量方法并完全删除了 ThreadPool 代码 . 看起来很简单 . 我的信息来自:http://www.albahari.com/threading/part2.aspx

这个例子向我展示了如何:

[此处下面的文字是网站的复制/粘贴]

容量为1的 Semaphore 类似于 Mutexlock ,除了 Semaphore 没有"owner" - 它与线程无关 . 任何线程都可以在 Semaphore 上调用 Release ,而使用 Mutexlock 时,只有获得该资源的线程才能释放它 .

在下面的示例中,十个线程在中间执行一个带有 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();
        }
    }
}

2 回答

  • 30

    注意:如果您将此限制为“3”只是因为您没有压倒运行应用程序的计算机,我首先确保这是一个问题 . 线程池应该为你管理这个 . 另一方面,如果你不想压倒其他一些资源,请继续阅读!


    您无法管理线程池的大小(或者实际上关于它的任何内容) .

    在这种情况下,我将使用信号量来管理对资源的访问 . 在您的情况下,您的资源正在运行Web抓取,或计算某些报告等 .

    为此,在静态类中,创建一个信号量对象:

    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方法,在这种方法中你要将你想要执行的工作排入一个全局的Blocking Queue对象 .

    同时,你有三个线程(你创建的 - 不在线程池中),弹出队列中的工作来执行 . 这不是那么棘手的设置,而且非常快速和简单 .

    例子:

  • 0

    它与任何其他类似的静态类,这意味着您使用它做的任何事情都会影响当前进程中的每个其他线程 . 它不会影响其他进程 .

    不过,我认为这是.NET中较大的设计缺陷之一 . 谁提出了使线程池静态的好主意?正如您的示例所示,我们经常需要专用于我们任务的线程池,而不会干扰系统中其他位置的无关任务 .

相关问题