计时器延迟随着时间的推移而退化或变得不一致?

发布于 2024-09-15 08:42:27 字数 469 浏览 2 评论 0原文

我希望有人能够阐明我可能会发生的事情。以下是所发生事件的摘要。

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

例如:我有一个计时器设置为每秒流逝一次。一段时间后,计时器开始随机延迟触发。如果我不重新启动应用程序,性能就会下降,并且计时器会越来越晚地触发,最终变成 3 或 4 秒,迫使我重新启动应用程序。我无法识别任何泄漏。 CPU 使用率没有上升,内存也没有上升,服务器也远未达到极限。谁能给我一些关于可能导致此问题的想法?

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

        timer.Start();
    }
}

I'm hoping someone can shed some light on what might be happening for me. Here's a summary of whats happening.

I have an application that does lots of "stuff". Its a pretty hefty application that does lots of number crunching using many threads. There are several timers that are used. Over a long period of time, the timers stop consistently invoking the elapsed handler.

For instance: I have a timer set to elapse every second. After a period of hours the timer starts randomly triggering late. If I do not restart the application the performance just degrades and the timers fire later and later eventually turning into 3 or 4 seconds, forcing me to restart the application. I have not been able to identify any leaks. CPU usage does not go up, memory does not go up, and the server is no where near being maxed out. Can anyone give me some ideas as to what may be causing this?

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

        timer.Start();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

妳是的陽光 2024-09-22 08:42:27

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

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

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

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

Is it possible you're exhausting the thread pool? Most timers invoke the handler using a threadpool thread. If all threadpool threads are in use, it will just get queued until one is available.

If that's the case switch some of your processing to use your own threads, not threadpool threads.

To test if you're exhausting the thread pool start up a background thread that periodically (a few times a second) checks ThreadPool.GetAvailableThreads and logs a message when the available is small (even if it's never actually zero when you check, if it sometimes approaches zero then it's likely this is the problem).

The size of the pool can be changed with ThreadPool.SetMaxThreads although that may not be the best solution. If you're using threadpool threads for longer running tasks, stop it. For long-running tasks use your own threads.

浮光之海 2024-09-22 08:42:27

您使用的计时器类非常重要

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

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

,该类仅将当前的 DateTime 写入日志文件

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

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

the timer class you use is really important

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

but I don't think the problem is the timer itself,
for instance try making an application using the same timer class

that ONLY writes the current DateTime to a log file

and leave it running for an extremely long period of time, you'll see that there's no such a 3/4 seconds delay

review your timer code and check that no shared resources are being accessed at the same time,
maybe the Timer is OK, but there's a bottleneck in the event handler function or in "something" that function uses

冰雪之触 2024-09-22 08:42:27

听起来可能并不是真正的同一个计时器,所以这里“泄漏”的资源是 GDI 句柄。

Sounds like maybe it's not really the same timer, and so the resources being "leaked" here are GDI handles.

凉薄对峙 2024-09-22 08:42:27

可能的解决方法:

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;
}

Possible workaround:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文