定时器有效吗?

时间:2012-10-24 19:29:47

标签: c# performance timer

我创建了一个用于以特定间隔读取邮箱的应用程序。如果有新邮件它下载附件创建pdf文件说100 +组合它并将其邮寄回特定列表。由于某些服务器策略可以将其转换为窗口服务。我使用了下面给出的代码

private System.Threading.Timer timer;
timer = new System.Threading.Timer(TimerTick, null, TimeSpan.Zero, TimeSpan.FromMinutes(1));

void TimerTick(object state)
{
  var minute = DateTime.Now.Minute;
  if (minute != lastMinute && minute % 5 == 0)
  {
    //check mail here
  }
}

实现这样的计时器是一种有效的方法吗?有没有更好的方法来处理这个?我担心性能,因为应用程序需要24 x7运行,因此如果效率低下,最终可能会使用更多的CPU内存。

计时器是此方案中唯一可用的最佳选项吗?

4 个答案:

答案 0 :(得分:4)

您应该监控服务的性能。如果您发现存在性能问题:

  1. 测量它
  2. 更改您的代码
  3. 再次测量
  4. 比你的测量值
  5. System.Threading.Timer是一个简单的轻量级计时器,它使用回调方法并由线程池线程提供服务。

    • 您可以考虑将System.Timers.Timer用于基于服务器的计时器 功能。

    可维护性和调试技巧:

    • 使用XML配置文件设置间隔,而无需更改代码。 这只会让您或管理员控制该服务。

    使用代码轻松调试您的服务:

    static void Main()
    {
    #if (!DEBUG)
        System.ServiceProcess.ServiceBase[] ServicesToRun;
        ServicesToRun = new System.ServiceProcess.ServiceBase[] { new Service1() };
        System.ServiceProcess.ServiceBase.Run(ServicesToRun);
    #else
        // Debug code: this allows the process to run as a non-service.
        // It will kick off the service start point, but never kill it.
        // Shut down the debugger to exit
        Service1 service = new Service1();
        service.EntryMethodHere(); // Your method that activates your timer
        // Put a breakpoint on the following line to always catch
        // your service when it has finished its work
        System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
    #endif 
    }
    

答案 1 :(得分:2)

简单地给定时器一个5分钟的时间,而不是1分钟的时间并且每隔5次检查一次邮件会更有效。

timer = new System.Threading.Timer(TimerTick, null, TimeSpan.Zero, TimeSpan.FromMinutes(5)); 

答案 2 :(得分:1)

计时器非常有效,但也许您应该使用TimeSpan.FromMinutes(5)来删除TimerTick中的低效条件。由于TimerTick将在ThreadPool线程中运行,因此您必须在再次检查邮件服务器之前检查上一个事件是否已完成。

private System.Threading.Timer timer = new System.Threading.Timer(TimerTick, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));

private bool FCheckingMails = false;
void TimerTick(object state)
{
    if (FCheckingMails) return;
    FCheckingMails = true;
    try
    {
        //check mail here
    }
    finally
    {
        FCheckingMails = false;
    }
}

有人可能会说FCheckingMails不是线程安全的,但它确实不需要。

如果您担心效率问题,则应检查运行数百万次/分钟的代码,而不是运行12次/小时的代码。

祝你好运。

答案 3 :(得分:0)

System.Threading.Timer在CPU和内存使用方面应该非常轻量级,因此我不会设想任何问题。更一般地说,这种工作通常由一个调度程序触发,该调度程序可以配置更多控制,并了解诸如周末,一天中的某些事情(例如,在每个月的第一天或最后一天进行处理)等等。

如果您沿着这条路走下去,那么请查看Quartz.Net,一个开源的.net cron作业调度程序。