【问题标题】:System.Threading.Timer callback not being hitSystem.Threading.Timer 回调未命中
【发布时间】:2013-02-25 09:14:41
【问题描述】:

我有一个 Windows 服务,除其他外,它需要每 24 小时进行一次数据库维护。 (SQL express,所以不能在数据库里面调度)

为此,我创建了一个带有数据库维护方法回调的计时器,但它似乎只被命中一次(我假设在创建计时器时)。 我认为这是由于计时器本身超出范围并被 GC 处理,但我尝试过的所有解决方案似乎都不起作用

服务的基本布局是这样的:

WindowsService.cs:

    protected override void OnStart(string[] args)
    {
        ThreadPool.QueueUserWorkItem(StartServices);
    }

    private void StartServices() { Manager.Start(); }

Manager.cs:

public class Manager
{
  private static Timer MaintenanceTimer;
  public static void Start()
  {
    MaintenanceTimer = new Timer(DoMaintenance);
    MaintenanceTimer.Change(new TimeSpan(0), new TimeSpan(24,0,0,0)); //I use 1 minute for testing
  }
}

显然,这段代码被严重简化了,但这几乎就是发生的事情。 如前所述,我认为 GC 是问题所在,这让我尝试了以下两件事:

  • 使用构造函数Timer(callback),所以它会提供一个 对回调的自我引用。但是,这仍然无法阻止 它不会超出范围,所以这是不行的。
  • 将定时器定义为 Manager 类中的静态变量。这应该阻止它 从曾经被GC'd,但似乎仍然没有被调用 每 24 小时一次。

在这件事上的任何帮助将不胜感激

【问题讨论】:

  • 失败:查找 GC.KeepAlive()
  • DoMaintenance 中会发生什么?是否有可能发生异常?这种行为是否在您的测试中发生?
  • @MitchWheat 我不是,虽然我假设这个建议,但我觉得这有点矫枉过正。我也很好奇它失败的原因。关于您的第二条评论: KeepAlive() 是否会阻止垃圾收集直到您发表声明?这些都是 void 方法,所以我不认为这有什么好处(尽管我可能在这里错了)
  • stackoverflow.com/questions/4962172/…。你能用System.Timers.Timer代替System.Timers.Timer

标签: c# .net timer windows-services


【解决方案1】:

最后我使用了一个常规的 System.Timers.Timer 来解决我的问题。 不过,我仍然不确定 System.Threading.Timer 哪里出了问题。

【讨论】:

    【解决方案2】:

    由于您无法在 SQL Server Express 中使用 SQL Server 代理,因此最好的解决方案是创建一个 SQL 脚本,然后将其作为计划任务运行。

    我很容易验证和维护,您可以有多个计划任务以适应您的备份计划/保留。

    我在定时任务中使用的命令是:

    C:\Program Files\Microsoft SQL Server\90\Tools\Binn\SQLCMD.EXE" -i"c:\path\to\sqlbackupScript.sql
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 2020-08-24
      • 1970-01-01
      相关资源
      最近更新 更多