我正在尝试从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();
}
这有效,但......
问题在于,每次加载页面时都会初始化计时器。如何创建仅初始化一次的计时器,并在不重新初始化的情况下从该时刻开始运行。此外,如果计时器或方法失败,如何引发异常或服务器出现故障,如何处理这种情况?如何重启计时器呢?
任何见解都会有所帮助!提前谢谢!
答案 0 :(得分:2)
您不希望在ASP.NET网页上执行此操作。 ASP.NET计时器专为在您离开之前在页面生命周期内发生的操作而设计。
如果你想做这样长时间的工作(即每小时24小时一次的任务)你会更好:
另一种选择,因为你的任务似乎与数据库数据传输密切相关,就是使用类似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)
在Global.asax中初始化计时器。 OnApplicationStart方法.. http://msdn.microsoft.com/en-us/library/1xaas8a2(v=vs.71).aspx
此处描述了类似的方法: http://www.west-wind.com/weblog/posts/2007/May/10/Forcing-an-ASPNET-Application-to-stay-alive
答案 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服务或本地系统来安排任务,一种选择是执行以下操作。当没有定时器时,我的模拟定时器解决方案。
此外,您还需要假设计时器不必在一小时内完全开火。
请记住,当您没有其他选项时,这是一种非常古怪的模拟计时器的方式。