【问题标题】:.Net max concurrent timer threads.Net 最大并发计时器线程
【发布时间】:2013-01-10 19:05:39
【问题描述】:

我正在尝试加载一个间隔进程队列。换句话说,我有一个队列,我希望队列中的每个项目都以单独的间隔运行。

我的问题是我似乎无法一次运行超过 25 个线程。我在 64 位机器上使用 .Net 4.5,默认最大线程数为 32768。

如何让我的应用运行我的机器可以处理的尽可能多的并发线程?

这是一个在我的生产代码中复制实际问题的示例应用程序:

class Program
{
    static void Main(string[] args)
    {
        System.Threading.ThreadPool.SetMaxThreads(200, 200);
        test t = new test();

        t.LoadUrls("http://www.google.com");

        while (1 == 1)
        {
            System.Threading.Thread.Sleep(1000);//refresh every 5 seconds
            Console.WriteLine(System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
        }
    }


    public class test
    {

        public void LoadUrls(string url)
        {
            for (int i = 0; i < 100; i++)
            {
                System.Threading.Timer t = new System.Threading.Timer(new System.Threading.TimerCallback(RunInterval), url, 0, 1000);
                Console.WriteLine("Loaded {0} feeds.", i);
            }
        }
        private static void RunInterval(object state)
        {
            string url = state as string;
            string data = "";

            using (System.Net.WebClient cl = new System.Net.WebClient())
            {
                Console.WriteLine("getting data for " + url);
                data = cl.DownloadString(url);
            }

            //do something with the data

        }
    }
}

此代码理论上应该在 2 秒左右后运行 198 个线程。

顺便说一句,这在我的原型应用中运行良好;它是用节点写的。但是,现在我无法让它在 c# 中正常工作......

回答: 问题实际上出在垃圾收集上,根本不是线程池问题。池完全能够假脱我扔给它的所有线程。诀窍是使用 System.Threading.Timer 的单参数构造函数;这将使计时器将自己用作信号量,从而避免 gc。

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 100; i++)
        {
            test t = new test();
            t.url = "http://www.google.com?" + i;
            System.Threading.Timer ti = new System.Threading.Timer(new System.Threading.TimerCallback(t.RunInterval));
            ti.Change(0, 1000);
        }

        while (1 == 1)
            System.Threading.Thread.Sleep(int.MaxValue);
    }


    public class test
    {
        public string url { get; set; }
        public void RunInterval(object state)
        {
            Console.WriteLine("getting data for " + this.url);
            string data = "";

            using (System.Net.WebClient cl = new System.Net.WebClient())
            {
                data = cl.DownloadString(this.url);
            }
        }
    }
}

我不确定您为什么希望 gc 收集计时器,但是我知道什么。

【问题讨论】:

  • 为什么要同时运行这么多线程?
  • 这是一个轮询服务。它必须以指定的时间间隔轮询 n 个提要。我可以制作一个精美的队列系统并运行 n 个单独的服务,每个服务只轮询 1 个提要。但是,我想做这个元;我希望程序启动每个单独的进程。
  • 你的答案还是错的。一切都可能被垃圾收集,排除计时器没什么特别的。您应该保留对所有计时器的引用,然后在完成后将其丢弃。否则,它们仍可能在垃圾收集时被丢弃。

标签: c# .net multithreading


【解决方案1】:

如何让我的应用运行我的机器可以处理的尽可能多的并发线程?

这是错误的方法。每个线程都是昂贵的,创建几百个,你的系统会严重退化。

您的代码使用线程池。池有一个算法来限制线程的数量。当您增加 Sleep() 时间时,您可能会看到更多线程。

更直接的方法是设置 ThreadPool.MinThreads。但期望更少的性能,而不是更多。

【讨论】:

  • 这并不昂贵...我有 64GB 的内存可以使用,但它永远不会超过 10MB。我希望它使用所有 64GB。你的建议是什么?
  • 另外,它使用的 CPU 永远不会超过我可用 CPU 的 1%。
  • 我已经添加了一些建议,但仍然是错误的方法。
  • 好奇你如何测量内存,每个线程应该使用 1 MB。而且 Sleep() 和 I/O 调用不使用 CPU,所以这就是为什么你看到 1%。一个很好的指标,表明更多线程无济于事。
  • 正确的方法是什么?我基本上想加载一个队列以从 n 个休息服务中检索数据。每个服务都有自己的刷新限制,因此它们都必须有单独的计时器。
【解决方案2】:

根据System.Threading.Timer

Use a TimerCallback delegate to specify the method you want the Timer to execute. The timer delegate is specified when the timer is constructed, and cannot be changed. The method does not execute on the thread that created the timer; it executes on a ThreadPool thread supplied by the system.

然后在System.Threading.Threadpool

There is one thread pool per process. Beginning with the .NET Framework 4, the default size of the thread pool for a process depends on several factors, such as the size of the virtual address space. A process can call the GetMaxThreads method to determine the number of threads. The number of threads in the thread pool can be changed by using the SetMaxThreads method. Each thread uses the default stack size and runs at the default priority.

【讨论】:

    【解决方案3】:

    您想使用名为 MaxDegreeOfParallelism 的属性,但您需要稍微修改您的代码。然后对其进行测试并找出要并行运行的最佳线程数。 这是链接:http://msdn.microsoft.com/en-us/library/system.threading.tasks.paralleloptions.maxdegreeofparallelism.aspx

    【讨论】:

    • MaxDegree 强加了一个上限。不是最低要求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多