【问题标题】:Timer Delay Degrades or becomes inconsistent over time?计时器延迟随着时间的推移而降级或变得不一致?
【发布时间】:2010-08-20 12:45:48
【问题描述】:

我希望有人能对我可能发生的事情有所了解。以下是正在发生的事情的摘要。

我有一个应用程序可以做很多“事情”。它是一个相当庞大的应用程序,它使用许多线程进行大量数字运算。有几个计时器被使用。在很长一段时间内,计时器会停止持续调用 elapsed 处理程序。

例如:我有一个计时器设置为每秒经过一次。几个小时后,计时器开始随机触发延迟。如果我不重新启动应用程序,性能只会下降,并且计时器稍后会触发,最终会变成 3 或 4 秒,迫使我重新启动应用程序。我无法识别任何泄漏。 CPU 使用率没有上升,内存没有上升,并且服务器远未达到极限。谁能给我一些关于可能导致这种情况的想法?

private void Timer_Elapsed(object source, ElapsedEventArgs e)
{
    if (seconds > 0)
    {
        seconds--;

        timer.Start();
    }
}

【问题讨论】:

  • 内存使用量根本没有增加?我对这类问题的第一个怀疑是垃圾收集......
  • 听起来您的系统运行速度越来越快,因此时间本身实际上正在变慢。尝试解开永动机。
  • .net 中有不止一个计时器类。你用的是哪一个? System.Thread.Timer、System.Threading.Timer、System.Windows.Forms.Timer
  • 什么样的定时器? System.Timers.Timer?
  • 我正在使用 System.Timers.Timer

标签: c# .net timer


【解决方案1】:

您是否可能正在耗尽线程池?大多数计时器使用线程池线程调用处理程序。如果所有线程池线程都在使用,它只会排队,直到有一个可用。

如果是这种情况,请切换您的某些处理以使用您自己的线程,而不是线程池线程。

要测试您是否耗尽了线程池,请启动一个后台线程,该线程会定期(每秒几次)检查 ThreadPool.GetAvailableThreads 并在可用时记录一条消息(即使在您检查时它实际上从未为零) ,如果它有时接近于零,那么很可能这就是问题所在)。

可以使用ThreadPool.SetMaxThreads 更改池的大小,尽管这可能不是最佳解决方案。如果您将线程池线程用于运行时间较长的任务,请停止它。对于长时间运行的任务,请使用您自己的线程。

【讨论】:

  • 这是个问题吗?为什么不将问题发布为问题而不是评论:)
  • @Nathan,Timwi 是对的,如果您还有其他问题,最好的办法是研究它或提出单独的问题。更容易获得正确答案,并让其他人在遇到相同问题时更容易找到答案。
  • @Nathan,尽管我认为应该单独提出额外的问题,但我还是用更多信息编辑了我的答案。
【解决方案2】:

你使用的计时器类真的很重要

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

但我认为问题不在于计时器本身, 例如尝试使用相同的计时器类制作应用程序

仅将当前日期时间写入日志文件

让它运行很长时间,你会发现没有这样的 3/4 秒延迟

查看您的计时器代码并检查是否没有同时访问共享资源, 也许计时器没问题,但事件处理函数或该函数使用的“某些东西”存在瓶颈

【讨论】:

    【解决方案3】:

    听起来可能不是同一个计时器,因此这里“泄漏”的资源是 GDI 句柄。

    【讨论】:

    • ...也可以通过任务管理器轻松检查。
    【解决方案4】:

    可能的解决方法:

    DateTime mayContinue = DateTime.MinValue;
    bool blockingUi = false;
    
    private void Timer_Elapsed(object source, ElapsedEventArgs e)
    {
        if( blockingUi )
        {
            if( DateTime.Now < mayContinue )
            {
                // Notify time remaining
                // Update the UI with a BeginInvoke
            }
            else
            {
                blockingUi = false;
                // Notify ready
                // Update the UI with a BeginInvoke                
            }
        }
    }
    
    private void BlockUi()
    {
        mayContinue = DateTime.Now.AddSeconds(30);
        blockingUi = true;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-22
      • 2018-07-28
      • 2014-04-15
      • 2011-12-09
      • 1970-01-01
      • 2014-02-04
      • 1970-01-01
      • 2021-07-17
      相关资源
      最近更新 更多