C# 定时任务实现方法 C#如何使用Timer实现定时任务

来源:这里教程网 时间:2026-02-21 17:42:25 作者:

System.Threading.Timer 是最轻量的定时触发方式

它不依赖 UI 线程,适合后台服务、控制台程序中执行无界面逻辑。但回调在

ThreadPool
线程上运行,不能直接操作 WinForms/WPF 控件,且没有内置的“暂停/继续”控制。

构造时需传入
TimerCallback
委托、状态对象、首次延迟(毫秒)、周期间隔(毫秒)
若希望只执行一次,把周期设为
Timeout.Infinite
必须手动调用
Dispose()
释放资源,否则可能造成内存泄漏或后台线程持续运行
回调中发生未捕获异常会终止该次执行,但不会影响后续触发——这点容易被忽略,建议包裹
try/catch
var timer = new System.Threading.Timer(state =>
{
    try
    {
        Console.WriteLine($"Tick at {DateTime.Now:HH:mm:ss}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error in timer callback: {ex.Message}");
    }
}, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5));

System.Timers.Timer 更适合需要事件模型的场景

它封装了

System.Threading.Timer
,提供
Elapsed
事件,支持
AutoReset
Enabled
控制,并可设置
SynchronizingObject
将回调封送到指定线程(如 Windows Forms 的 UI 线程)。

默认
AutoReset = true
,即周期性触发;设为
false
则只触发一次
Enabled = false
可暂停,设回
true
即恢复,比手动
Change()
更直观
在 WinForms 中可赋值
timer.SynchronizingObject = this;
,使
Elapsed
回调自动进入 UI 线程
注意:未调用
Stop()
或设
Enabled = false
前,对象被 GC 回收时不会自动停掉定时器
var timer = new System.Timers.Timer(3000);
timer.Elapsed += (s, e) => Console.WriteLine($"Fired at {e.SignalTime:HH:mm:ss}");
timer.AutoReset = true;
timer.Enabled = true;

System.Windows.Forms.Timer 仅限 WinForms UI 线程使用

它是唯一基于消息循环的定时器,所有回调都在创建它的 UI 线程中执行,天然线程安全,但**不能用于控制台、WPF 或后台服务**。一旦窗体关闭或线程退出,它自动失效。

间隔单位是毫秒,最大值约 2^31−1(约 24.8 天),但实际建议不超过几分钟,避免精度下降 启用只需设置
Interval
后调用
Start()
;禁用用
Stop()
如果在回调中执行耗时操作(如网络请求、文件读写),会阻塞 UI 线程,导致界面卡顿——这是最常见的误用点
var timer = new System.Windows.Forms.Timer();
timer.Interval = 2000;
timer.Tick += (s, e) => label1.Text = DateTime.Now.ToString("HH:mm:ss");
timer.Start();

Task.Run + Task.Delay 组合更适合异步定时逻辑

当你的定时任务本质是“每隔 N 秒做一次异步操作”(如调用 HTTP API、写数据库),用

Task.Delay
配合循环比传统 Timer 更自然,也更容易取消和错误传播。

必须配合
CancellationToken
实现可控停止,否则
while(true)
会永远挂住
每次循环开头先
await Task.Delay(..., token)
,再执行业务逻辑,避免因前次耗时过长导致堆积
异常会抛出到外层
Task
,可用
await task
捕获,或用
task.ContinueWith(..., TaskContinuationOptions.OnlyOnFaulted)
var cts = new CancellationTokenSource();
var task = Task.Run(async () =>
{
    while (!cts.Token.IsCancellationRequested)
    {
        try
        {
            await Task.Delay(5000, cts.Token);
            await DoAsyncWork(); // e.g., HttpClient.GetAsync(...)
        }
        catch (OperationCanceledException)
        {
            break;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Async job failed: {ex.Message}");
        }
    }
}, cts.Token);
定时器的“准时性”受系统调度、GC、线程池负载影响,不要假设它能精确到毫秒级;真正对精度敏感的任务(如音视频同步、工业控制)应使用更高优先级线程或专用硬件方案。

相关推荐