MultiThreading:限制并发线程

时间:2011-05-16 12:46:25

标签: c# multithreading threadpool semaphore

我需要开发一个使用多线程的应用程序。

基本上,我有一个包含大约20万行的DataTable。 从每一行开始,我需要一个字段,将其与网页进行比较, 然后将其从数据表中删除。

问题是,服务于这些页面的服务器对并发请求有限制。 所以最多我可以同时要求3页。

我想通过使用线程池来实现这一点, 我甚至管理构建一个简单的应用程序(锁定数据表) 但我无法限制并发线程(即使使用SetMaxThreads),它似乎只是忽略了限制。

有没有人做过类似的东西? 我很乐意看到。

我尝试过使用信号量,但遇到了问题:

        static SemaphoreSlim _sem = new SemaphoreSlim(3);    // Capacity of 3
    static List<string> records = new List<string>();

    static void Main()
    {
        records.Add("aaa");
        records.Add("bbb");
        records.Add("ccc");
        records.Add("ddd");
        records.Add("eee");
        records.Add("fff");
        records.Add("ggg");
        records.Add("iii");
        records.Add("jjj");

        for (int i = 0; i < records.Count; i++ )
        {
            new Thread(ThreadJob).Start(records[i]);
        }

        Console.WriteLine(records.Count);
        Console.ReadLine();
    }

    static void ThreadJob(object id)
    {
        Console.WriteLine(id + " wants to enter");
        _sem.Wait();
        Console.WriteLine(id + " is in!");           // Only three threads
        //Thread.Sleep(1000 * (int)id);               // can be here at
        Console.WriteLine(id + " is leaving");       // a time.

        lock (records)
        {
            records.Remove((string)id);
        }

        _sem.Release();
    }

这很好地运行,唯一的问题是,

Console.WriteLine(records.count);

返回不同的结果。 即使我知道它发生了,因为并非所有线程都已完成(我在删除所有记录之前调用records.count)我无法找到如何等待所有完成。

4 个答案:

答案 0 :(得分:2)

答案 1 :(得分:1)

为什么不使用Parallel Extensions - 这会让事情变得更容易。

无论如何,你可能想要看的东西就像信号量。我在一两个月后写了一篇关于这个主题的博客文章,你可能觉得它很有用:https://colinmackay.scot/2011/03/30/using-semaphores-to-restrict-access-to-resources/

答案 2 :(得分:0)

你可以用 如果您在.net 3.5

下,请Semaphore
  

SemaphoreSlim in。net 4.0

答案 3 :(得分:0)

首先,应该     Console.WriteLine(id +“离开”); 在锁定之后和它发布信号量之前不会稍晚一点?

至于实际等待所有线程的完成,从长远来看,Groo的答案看起来更好,更强大,但作为这个特定代码的更快/更简单的解决方案,我想你也可以逃脱只是按顺序在你想要等待的所有线程上调用.Join()。

static List<Thread> ThreadList = new List<Thread>(); // To keep track of them

然后在启动线程时,将当前新的Thread行替换为:

ThreadList.Add(new Thread(ThreadJob).Start(records[i]));

然后就在Console.WriteLine之前:

foreach( Thread t in ThreadList )
{
    t.Join();
}

如果任何线程没有终止,这将锁定,如果你想知道 - 哪些线程还没有完成,这个方法将不起作用。

相关问题