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

C# Windows Service多定时器问题:基于动态List创建的定时器仅最后一个生效的解决方法问询

解决Windows服务中仅最后一个定时器工作的问题

嘿,这个问题我之前也踩过坑——典型的C# foreach循环变量捕获陷阱!

问题根源

在旧版本的C#(C# 5之前)里,foreach循环的迭代变量item是在循环体外声明的,整个循环过程中共用同一个变量引用。你在循环里创建的每个定时器,它们的事件处理程序都会捕获这个共享的item变量。等循环执行完,所有定时器捕获的引用都指向了列表的最后一个元素,自然只有最后一个定时器能正常工作。

快速修复方案

最直接的解决办法是在循环内部创建当前元素的局部副本,让每个定时器捕获这个独立的局部变量:

protected override void OnStart(string[] args)
{
    //** CARICA CONFIGURAZIONI **//
    List<Configurazione> Configurazioni = ModulReader.GetModulCopyDirectory();
    int i = 0;
    foreach (var item in Configurazioni )
    {
        i++;
        // 关键步骤:创建当前item的局部副本
        var currentItem = item;
        
        string data = string.Format("CONFIGURAZIONE {0}",i.ToString());
        string folder = @"C:\temp\OUT\";
        string fileName = "Test.txt";
        string fullPath = folder + fileName;
        File.AppendAllText(fullPath, data);

        var timer = new CustomTimer
        {
            Interval = Int32.Parse(currentItem.TIMER.Trim()),
            configurazione = currentItem
        };
        timer.Elapsed += Lavorazione;
        timer.Start();
    }
}

如果你用的是C# 5及以上版本(VS2012或更高),也可以改用for循环遍历列表,这样每个迭代的变量都是独立的:

protected override void OnStart(string[] args)
{
    List<Configurazione> Configurazioni = ModulReader.GetModulCopyDirectory();
    for (int i = 0; i < Configurazioni.Count; i++)
    {
        var currentItem = Configurazioni[i];
        string data = string.Format("CONFIGURAZIONE {0}", (i+1).ToString());
        
        // 后续代码和上面一致,使用currentItem代替item
        string folder = @"C:\temp\OUT\";
        string fileName = "Test.txt";
        string fullPath = folder + fileName;
        File.AppendAllText(fullPath, data);

        var timer = new CustomTimer
        {
            Interval = Int32.Parse(currentItem.TIMER.Trim()),
            configurazione = currentItem
        };
        timer.Elapsed += Lavorazione;
        timer.Start();
    }
}

额外优化建议

为了避免服务停止时的内存泄漏,建议把所有创建的定时器保存到一个类级别的集合中,在OnStop方法里统一清理:

  1. 在类中添加一个私有列表:
private List<CustomTimer> _activeTimers = new List<CustomTimer>();
  1. 在创建定时器时添加到列表:
var timer = new CustomTimer
{
    Interval = Int32.Parse(currentItem.TIMER.Trim()),
    configurazione = currentItem
};
timer.Elapsed += Lavorazione;
timer.Start();
_activeTimers.Add(timer); // 添加到列表
  1. 在OnStop方法中清理定时器:
protected override void OnStop()
{
    foreach (var timer in _activeTimers)
    {
        timer.Stop();
        timer.Elapsed -= Lavorazione; // 移除事件绑定
        timer.Dispose(); // 释放资源
    }
    _activeTimers.Clear();
}

这样修改后,所有定时器应该都能正常触发各自的任务了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 23:38:13