【问题标题】:C# ASP.NET: Timer - How to execute a command every quarter hour?C# ASP.NET:计时器 - 如何每一刻钟执行一次命令?
【发布时间】:2014-08-01 16:48:50
【问题描述】:

我想每刻钟每刻钟执行一个命令。 (24 小时制)

所以在 00:00:00、00:15:00、00:30:00 做某事一直到 23:45:00

这里有一段代码可以帮助你理解我在说什么。

  protected void UpdateTimer_Tick(object sender, EventArgs e)
  {
    DateStampLabel.Text = DateTime.Now.ToString("hh:mm:ss");

    //CREATE FOR LOOP TO REFRESH AT EVERY QUARTER HOUR
        if (DateStampLabel.Text == "00:00:00")
        {
            Response.Redirect(Request.RawUrl);
        }
        if (DateStampLabel.Text == "00:15:00")
        {
            Response.Redirect(Request.RawUrl);
        }
        if (DateStampLabel.Text == "00:30:00")
        {
            Response.Redirect(Request.RawUrl);
        }
        if (DateStampLabel.Text == "00:45:00")
        {
            Response.Redirect(Request.RawUrl);
        }
        ...
        ...
        ...
        if (DateStampLabel.Text == "23:45:00")
        {
            Response.Redirect(Request.RawUrl);
        }
    }

如何使用 for 循环实现相同的代码?

【问题讨论】:

  • “带有 for 循环”是什么意思?您不会循环代码中的任何内容。顺便说一句,使用 UI 文本元素来确定当前时间看起来不太可靠。此外,ASP.NET 绝对不是用于重复后台任务的技术。 Windows 服务或计划的控制台应用程序将更适用。
  • @David 的评论非常有用。首先,您错误地使用了计时器滴答事件。 Timer 课程应该在预定的时间间隔打勾并运行您的活动。无论如何,您甚至都不需要使用它 - 正如@David 所说,使用 Windows 服务或控制台应用程序,并将 Windows 任务计划程序设置为每 15 分钟运行一次。
  • @Joe 这怎么没用?你不能在 ASP.NET 中做你想做的事——你会点击页面,然后在大约 60 秒后请求将超时,你将永远无法通过循环的任何部分。我们正在告诉您如何以实际可行的方式实现您想要的。
  • @Joe:如果您坚持以绝对最错误的方式做事,那么恐怕您在 Stack Overflow 上找不到太多“有用”的帮助。本网站的目的是分享有关软件开发的有意义和有用的知识,而不是为了迎合您。
  • 提示:您可能不希望在计划时间运行的代码精确到秒,即== "00:45:00"。模糊的时间安排和其他任务可能会导致您的代码运行有点晚,并且根据您的概念设计,它找不到匹配项并且会失败。

标签: c# asp.net loops for-loop timer


【解决方案1】:

这种事情真的不能(也不应该)在服务器端完成。服务器端唯一合理的方法是使用计时器在后台线程上进行回调并管理一组客户端回调。

我的意思是,您所说的不仅要为每个连接的远程用户长时间绑定 TCP 连接,还要绑定 ASP.NET 工作线程,对吗?哎呀。 :-)

您可以在浏览器中使用 JavaScript,而不是如此努力地占用有限的服务器资源:

window.onload = function(e){
    setInterval( function() {
        location.reload()
    }, 900000 );
}

编辑:公认的答案似乎有很多活动部件,并且会产生大量热量和烟雾而没有真正的好处。我将原始伪代码更新为完整的解决方案(上),但也演示了另一种方法(下),它使用不同的计时器 API,但在功能上是等效的。基本上,这只需要从window.onload 事件处理程序调用的一行代码。

我在代码审查中会遇到的问题包括:

  • 为什么 HTML 标签用 runat="server" 修饰?

  • 为什么任意运行96次就停止了?

  • 为什么要创建一个立即执行并且只执行一次的计时器,只是为了调用一个位于热循环中的函数(提高 CPU 利用率)检查时间,而实际上它所做的只是最终刷新页面,运行立即回调计时器以重新启动热循环?

  • 为什么不直接将定时器设置为 15 分钟后回调并刷新页面?

我在下面包含了一个完整的功能示例,它以均匀的间隔重新加载页面。这与 setTimeout setInterval 的工作方式完全相同。

我将其设置为每隔几秒,只是为了演示效果。但真正的要点是页面加载,一旦 UI 准备就绪,设置一个计时器回调到一个函数,该函数在间隔过去后简单地刷新页面。您不必在热循环中检查时间、提高 CPU 利用率(消耗电池寿命、从其他应用程序窃取 CPU 等)。

一旦页面再次完成渲染,页面刷新计时器回调将再次设置。这里实际上只有一行相关的代码——setTimeout 调用。其余的只是在页面加载时显示当前时间戳,以证明刷新按预期工作。

<html>
    <script language="JavaScript">

        refreshInterval = 0.0333 * 60 * 1000; // minutes * seconds * ms

        window.onload = function(e){
            var now = new Date();
            var nowUI = now.getDate() + "/" + (now.getMonth()+1) + "/" + now.getFullYear() + " @ " + now.getHours() + ":"+ now.getMinutes() + ":" + now.getSeconds();

            document.getElementById('blah').innerHTML = nowUI;

            setTimeout( function(){ location.reload() }, refreshInterval );
        }

    </script>

    <head></head>
    <body>
        <div id='blah'>0</div>
    </body>
</html>

【讨论】:

    【解决方案2】:

    好的,我想通了。这就是我想做的。

     <script>
      function startTime() {
      document.getElementById('lblClientTime').innerHTML = moment().format('HH:mm:ss');
      var t = setTimeout(function () { startTime() }, 0);
    
            refresh();
        }
    
        function refresh() {
            //REFRESHES WEB FORM EVERY QUARTER HOUR
            for (var i = 0; i < 96; i++) {
                var startTime = moment().startOf('day').add(i * 900000).format('HH:mm:ss');
    
                if (lblClientTime.textContent == startTime) {
                    location.reload();
                }
            }
        }
    </script>
        <div id="lblClientTime" runat="server"></div>
    </body>
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多