【问题标题】:High CPU usage in C# multi-threaded codeC# 多线程代码中的高 CPU 使用率
【发布时间】:2015-11-11 16:29:14
【问题描述】:

我在编写好的多线程代码方面没有太多知识。我最近刚刚开始在一个必要的项目上工作。我编写了以下代码,可以按我的意愿工作,但是 CPU 使用率非常高。我假设这是由于我使用线程的方式。如果有人能指出以下代码中的缺陷并告诉我如何修复它以使 CPU 使用率不那么高,我将不胜感激。

var numberOfMinutes = Convert.ToInt32(ConfigurationManager.AppSettings["NumberOfMinutesToRun"]);
var traversals = DbLayer.GetTraversals().ToList();
var numberOfThreads = Convert.ToInt32(ConfigurationManager.AppSettings["NumberOfThreads"]);
var threads = new List<Thread>(numberOfThreads);
var counter = 1;
var s = new Stopwatch();
s.Start();
var sync = new object();
while (s.Elapsed < TimeSpan.FromMinutes(numberOfMinutes))
{
    for (var i = 0; i < (numberOfThreads - threads.Count); i++)
    {
        var counter1 = counter; // due to closure.
        var traversal = traversals.FirstOrDefault(t => t.Id == counter1);
        var threadStart = new ThreadStart(new CallHelper(traversal).Migrate);
        var i1 = i;
        threadStart += () =>
                       {
                            threads.RemoveAt(i1);
                       };
        threads.Insert(i, new Thread(threadStart) {IsBackground = true});
        threads[i].Start();
        lock (sync)
        {
            counter++;
            if (counter > 6)
            {
                counter = 1;
            }
        }
    }
}
s.Stop();

我更新了代码以显示我希望对我有所帮助的内容。遍历集合仅包含 6 个项目。计数器用于确保线程在遍历集合中的 6 个项目中的每一个中旋转。 CallHelper 类只是在每次遍历时执行一个非常长的运行任务。该应用程序旨在使用可配置数量的线程在可配置的时间内对 6 个不同的对象执行长时间运行的任务。希望我已经填补了足够多的空白。

【问题讨论】:

  • 请提供重现问题的最小、完整和可验证的示例。 stackoverflow.com/help/mcve
  • 我不确定这段代码应该做什么。这里的目标是什么? CallHelper().Migrate 是做什么的? counter 的目的是什么?为什么要使用while 循环和for 循环来生成线程?
  • 你使用了多少线程?并发布有关 threadStart 的代码。
  • 如果不是关键循环,那么 Thread.Sleep(1) 会在很大程度上降低 CPU 利用率。
  • 我投票决定将此问题作为离题结束,因为它对 OP 来说太具体了,对其他人没有用处。 (抱歉,虽然我最近读过它,但我找不到讨论使用密切原因的元帖子。)

标签: c# multithreading cpu-usage


【解决方案1】:

网上有多种资源可用于编写good 和高效的多线程代码。 “好”通常是指工作和健壮的代码。对于高效的代码,请使用embedded 资源。

我只扫描了您的代码,但可以看到各种问题并提供建议。

  1. 使用线程池。构建和拆除线程非常昂贵。
  2. 尽可能少地重复循环(如上所述)。
  3. 当您需要延迟时,使用休眠而不是忙循环。
  4. 使用重要的代码来测试效率。如果您正在针对琐碎的代码进行测试,那么您的利用率将由程序(而不仅仅是线程)设置和拆除来主导,这非常昂贵并且会主导 cpu 利用率。
  5. 衡量您感兴趣的代码的利用率并排除您不感兴趣的代码,例如应用程序设置和拆除。

【讨论】:

  • 我接受了这个作为答案,因为你是对的。上面的代码有几个“问题”,因为您的输入非常有帮助。我已经重写了内部循环,CPU 使用率很低,但吞吐量非常好。我还在内部循环的末尾添加了一个 Thread.Sleep(1000) 。我还将听取您的建议并查看如何使用“线程池”。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-09
  • 2018-09-13
相关资源
最近更新 更多