C#Timer来填充数据库

时间:2012-04-17 21:29:05

标签: c# mysql sql-server postgresql timer

我正在尝试从MSSQL和PostrgeSQL数据库中检索数据,以便定期(每小时)将其填充到MySQL数据库中。

基于我所做的研究,我想使用C#Timer来做到这一点。但是,我并不完全了解计时器的工作方式。 我在Page_Load中声明它,设置已用事件处理程序并从事件处理程序调用方法。

protected void Page_Load(object sender, EventArgs e)
{
    int duration = 100 * 60 * 5; //milliseconds * seconds * minutes

    // Create a timer with a two second interval.
    System.Timers.Timer timer = new System.Timers.Timer(duration);

    // Hook up the Elapsed event for the timer.
    timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);

    timer.Enabled = true;
}

void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    cf();
}

这有效,但......

问题在于,每次加载页面时都会初始化计时器。如何创建仅初始化一次的计时器,并在不重新初始化的情况下从该时刻开始运行。此外,如果计时器或方法失败,如何引发异常或服务器出现故障,如何处理这种情况?如何重启计时器呢?

任何见解都会有所帮助!提前谢谢!

5 个答案:

答案 0 :(得分:2)

您不希望在ASP.NET网页上执行此操作。 ASP.NET计时器专为在您离开之前在页面生命周期内发生的操作而设计。

如果你想做这样长时间的工作(即每小时24小时一次的任务)你会更好:

  • 使用带有System.Timer或
  • 的always on Windows服务
  • 使用Windows计划任务,每小时计划1次,启动控制台应用程序。

另一种选择,因为你的任务似乎与数据库数据传输密切相关,就是使用类似SSIS或其他替代ETL工具(Extract-Transform-Load)的东西

答案 1 :(得分:1)

其他答案触及此;我会碰到头脑:ASP.NET中的计时器是个坏主意。

之所以与ASP.NET生命周期有关。非常简短的是,为每个页面加载实例化一个Page类(您的代码隐藏)的实例。将生成的页面作为HTML输出到客户端的浏览器后,Page实例将保留范围并被销毁。这意味着你的计时器设置为从现在开始运行一小时,它将在它的Tick事件发生之前完全消失;对于简单页面,Page类可以在内存中保留不到一秒钟。

在某些情况下,您可以通过将Timer存储在Session中来解决此问题,只要用户与站点的连接存在,就会持续存在。但是,Sessions通常比一小时更早出现(15分钟是一个常见标准;拥有大量私人数据的网站,如网上银行应用程序,超时时间可达5分钟)。

因此,我重申,不要在ASP.NET代码中使用Timers。相反,您可以在Web服务器(或应用服务器)上运行的Windows服务中使用Timer,该服务器每小时执行一次此数据提取。它可以通过Web应用程序提供信息,例如哪些用户连接,可能是通过访问ASP.NET使用的数据库来验证/授权在线用户帐户。

如果它只是一个做刷新数据的网络应用程序,那么我会在页面上保留一个隐藏字段或JavaScript变量,指示下次应该提取数据。设置文档加载时的JavaScript timeout(),触发AJAX回调到服务器以运行事件处理程序,该处理程序使用来自其他两个DB的数据刷新MySql。始终验证是否应该在代码隐藏中发生此数据刷新(可能通过在Session或ViewState中保持相同的值),否则使用FireBug或Chrome构建的插件将您自己的页面代码转换为DoS机制是微不足道的 - 代码编辑器。如果更新时间已过,您也可以从Page_Load触发相同的事件,在用户禁用JavaScript的情况下覆盖自己;如果实际上是时候这样做,用户刷新页面将会提取最新数据。

答案 2 :(得分:0)

答案 3 :(得分:0)

首先,您可能想要将初始化程序移动到您声明所有其他变量。接下来,您可以在页面中加载一个函数,将您的间隔时间设置为到达下一个小时所需的时间。这就是我所做的。

    private void SetTimer()
    {
        timer1.Stop();
        var timeOfDay = DateTime.Now.TimeOfDay;
        var nextFullHour = TimeSpan.FromHours(Math.Ceiling(timeOfDay.TotalHours));
        var delta = (nextFullHour - timeOfDay).TotalMilliseconds;
        timer1.Interval = (int)delta;
        timer1.Start();
    }

授予您的方案可能会略有不同,但这可能对您有所帮助。

答案 4 :(得分:0)

假设您无法访问控制台应用程序或Windows服务或本地系统来安排任务,一种选择是执行以下操作。当没有定时器时,我的模拟定时器解决方案。

此外,您还需要假设计时器不必在一小时内完全开火。

  1. 在数据库中添加一个表,记录上次运行计时器作业的时间。
  2. 页面加载完成后,检查自上次运行计时器作业以来是否已经过了一个小时。
  3. 如果超过一个小时,则在此时执行时间作业。
  4. 当时间作业开始记录到它启动的数据库时,从而阻止另一个作业启动。
  5. 请记住,当您没有其他选项时,这是一种非常古怪的模拟计时器的方式。