You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何简单C#自动化脚本占用大量CPU资源?

优化每分钟执行任务的脚本CPU占用率问题

我写了个自动化脚本,要求每分钟整分(00秒时)执行一次任务。测试阶段,被调用的任务只是往控制台和文本文件里写入运行记录和时间。但这个脚本在i7 8750H处理器上占了约17%的CPU,我对资源占用优化完全不懂。

脚本完整代码如下:

Logger.WriteLine("Program starting... @ " + DateTime.Now.ToString("HH:mm:ss"));

static void TestTask()
{
    string currentTime = DateTime.Now.ToString("HH:mm:ss");
    Logger.WriteLine("Test task ran at: " + currentTime);
}

// This currently runs forever, as there is no boolean condition evaluated to false to break the while loop (which is expected behavior)
while (true)
{   
    // Every minute on the minute 
    if (DateTime.Now.Second == 0)
    {
        TestTask();
        Thread.Sleep(1000);
    }
}

其中Logger.WriteLine是我自定义的类,功能类似Console.WriteLine,同时会把内容存到StringBuilder,再通过StringWriter写入桌面的.txt文件,这会不会是高CPU的原因?另外我用Python写了逻辑完全一样的程序,CPU占用率也差不多。两个程序的.exe内存占用约5MB,符合预期,现在只需要降低CPU占用率,求可行的优化方案。


优化方案

1. 替换高频轮询的循环逻辑

当前CPU占用高的核心原因是**while(true)循环一直在高频轮询DateTime.Now.Second == 0**,CPU几乎全程在做无效判断,没有真正休眠。

你可以计算下一次整分到来前需要等待的毫秒数,直接让线程休眠到目标时间,彻底避免无意义的轮询:

Logger.WriteLine("Program starting... @ " + DateTime.Now.ToString("HH:mm:ss"));

static void TestTask()
{
    string currentTime = DateTime.Now.ToString("HH:mm:ss");
    Logger.WriteLine("Test task ran at: " + currentTime);
}

while (true)
{
    var now = DateTime.Now;
    // 计算距离下一个整分的毫秒数:(60-当前秒数)*1000 - 当前毫秒数
    int waitMs = (60 - now.Second) * 1000 - now.Millisecond;
    
    if (waitMs <= 0)
    {
        // 刚好处于整分,直接执行任务后等待60秒
        TestTask();
        Thread.Sleep(60000);
    }
    else
    {
        // 休眠到下一个整分时刻
        Thread.Sleep(waitMs);
        TestTask();
        // 避免同一分钟内重复触发,额外休眠1秒
        Thread.Sleep(1000);
    }
}

2. 验证Logger类的性能影响

虽然轮询是主因,但可以快速验证Logger是否有额外影响:临时把TestTask()里的Logger.WriteLine换成普通Console.WriteLine,如果CPU占用没有明显变化,说明Logger不是问题;如果有下降,再优化Logger的写入逻辑:

  • 避免每次写入都打开/关闭文件(如果你的实现是单次写入就操作文件),可以缓存多条记录后批量写入
  • 确保StringBuilder和StringWriter的操作没有冗余逻辑(比如频繁扩容、重复拼接)

3. 更优雅的定时方案(C#专属)

如果是C#程序,完全可以用System.Timers.Timer或System.Threading.Timer实现定时任务,彻底摆脱手动循环:

Logger.WriteLine("Program starting... @ " + DateTime.Now.ToString("HH:mm:ss"));

static void TestTask()
{
    string currentTime = DateTime.Now.ToString("HH:mm:ss");
    Logger.WriteLine("Test task ran at: " + currentTime);
}

// 计算第一次执行的初始延迟,确保在整分触发
var now = DateTime.Now;
int initialDelay = (60 - now.Second) * 1000 - now.Millisecond;
if (initialDelay < 0) initialDelay += 60000;

// 创建定时器,每分钟执行一次
var timer = new System.Timers.Timer(60000);
timer.Elapsed += (sender, e) => TestTask();
timer.AutoReset = true;
timer.Start();

// 保持程序运行
Console.ReadLine();

内容的提问来源于stack exchange,提问作者mv1999

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 13:20:49