C# 多线程代码中 CPU 的高使用率
High CPU usage in C# multi-threaded code
我在编写好的多线程代码方面知识不多。我最近才开始从事一个有必要的项目。我已经编写了以下代码,它可以按我想要的方式运行,但是 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 class 只是在每次遍历时执行一个很长的 运行 任务。该应用程序旨在使用可配置数量的线程在可配置的时间内对 6 个不同的对象执行长 运行 任务。希望我已经填补了足够多的空白。
有多种在线资源可用于编写 good and efficient multi-threaded code. "Good" generally refers to working and robust code. For efficient code, use embedded 资源。
我只扫描了你的代码,但可以看到各种各样的问题,可以提供建议。
- 使用线程池。构建和拆除线程非常昂贵。
- 尽可能少地重复循环(如上所述)。
- 当你需要延迟时,使用睡眠而不是忙循环。
- 使用非平凡代码来测试效率。如果您正在针对琐碎的代码进行测试,您的利用率将主要由程序(而不仅仅是线程)设置和拆除,这是非常昂贵的并且将主导 cpu 利用率。
- 衡量您感兴趣的代码的利用率并排除您不感兴趣的代码,例如应用程序安装和拆卸。
我在编写好的多线程代码方面知识不多。我最近才开始从事一个有必要的项目。我已经编写了以下代码,它可以按我想要的方式运行,但是 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 class 只是在每次遍历时执行一个很长的 运行 任务。该应用程序旨在使用可配置数量的线程在可配置的时间内对 6 个不同的对象执行长 运行 任务。希望我已经填补了足够多的空白。
有多种在线资源可用于编写 good and efficient multi-threaded code. "Good" generally refers to working and robust code. For efficient code, use embedded 资源。
我只扫描了你的代码,但可以看到各种各样的问题,可以提供建议。
- 使用线程池。构建和拆除线程非常昂贵。
- 尽可能少地重复循环(如上所述)。
- 当你需要延迟时,使用睡眠而不是忙循环。
- 使用非平凡代码来测试效率。如果您正在针对琐碎的代码进行测试,您的利用率将主要由程序(而不仅仅是线程)设置和拆除,这是非常昂贵的并且将主导 cpu 利用率。
- 衡量您感兴趣的代码的利用率并排除您不感兴趣的代码,例如应用程序安装和拆卸。