C# 带有计时器的 .NET Windows 服务停止响应
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/397744/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
.NET Windows Service with timer stops responding
提问by Biri
I have a windows service written in c#. It has a timer inside, which fires some functions on a regular basis. So the skeleton of my service:
我有一个用 C# 编写的 Windows 服务。它内部有一个计时器,可以定期触发一些功能。所以我的服务的骨架:
public partial class ArchiveService : ServiceBase
{
Timer tickTack;
int interval = 10;
...
protected override void OnStart(string[] args)
{
tickTack = new Timer(1000 * interval);
tickTack.Elapsed += new ElapsedEventHandler(tickTack_Elapsed);
tickTack.Start();
}
protected override void OnStop()
{
tickTack.Stop();
}
private void tickTack_Elapsed(object sender, ElapsedEventArgs e)
{
...
}
}
It works for some time (like 10-15 days) then it stops. I mean the service shows as running, but it does not do anything. I make some logging and the problem can be the timer, because after the interval it does not call the tickTack_Elapsed function.
它工作一段时间(如 10-15 天)然后停止。我的意思是该服务显示为正在运行,但它没有做任何事情。我做了一些日志记录,问题可能出在计时器上,因为在间隔之后它不会调用 tickTack_Elapsed 函数。
I was thinking about rewrite it without a timer, using an endless loop, which stops the processing for the amount of time I set up. This is also not an elegant solution and I think it can have some side effects regarding memory.
我正在考虑在没有计时器的情况下重写它,使用无限循环,这会在我设置的时间内停止处理。这也不是一个优雅的解决方案,我认为它可能会对内存产生一些副作用。
The Timer is used from the System.Timers namespace, the environment is Windows 2003. I used this approach in two different services on different servers, but both is producing this behavior (this is why I thought that it is somehow connected to my code or the framework itself).
Timer 是从 System.Timers 命名空间使用的,环境是 Windows 2003。我在不同服务器上的两个不同服务中使用了这种方法,但两者都产生了这种行为(这就是为什么我认为它以某种方式连接到我的代码或框架本身)。
Does somebody experienced this behavior? What can be wrong?
有人经历过这种行为吗?有什么问题?
Edit:
编辑:
I edited both services. One got a nice try-catch everywhere and more logging. The second got a timer-recreation on a regular basis. None of them stopped since them, so if this situation remains for another week, I will close this question. Thank you for everyone so far.
我编辑了这两个服务。一个人在任何地方都得到了很好的尝试捕获和更多的日志记录。第二个定期进行计时器娱乐。自从他们之后,他们都没有停止过,所以如果这种情况再持续一周,我将结束这个问题。到目前为止,谢谢大家。
Edit:
编辑:
I close this question because nothing happened. I mean I made some changes, but those changes are not really relevant in this matter and both services are running without any problem since then. Please mark it as "Closed for not relevant anymore".
我关闭这个问题,因为什么也没发生。我的意思是我做了一些更改,但这些更改与此事无关,并且这两个服务从那时起都没有任何问题地运行。请将其标记为“因不再相关而关闭”。
采纳答案by Nickolodeon
Like many respondents have pointed out exceptions are swallowed by timer. In my windows services I use System.Threading.Timer. It has Change(...) method which allows you to start/stop that timer. Possible place for exception could be reentrancy problem - in case when tickTack_Elapsed executes longer than timer period. Usually I write timer loop like this:
就像许多受访者指出的异常被计时器吞噬一样。在我的 Windows 服务中,我使用 System.Threading.Timer。它具有 Change(...) 方法,可让您启动/停止该计时器。可能发生异常的地方可能是重入问题 - 如果 tickTack_Elapsed 执行时间长于计时器周期。通常我这样写定时器循环:
void TimeLoop(object arg)
{
stopTimer();
//Do some stuff
startTimer();
}
You could also lock(...)
your main loop to protect against reentrancy.
您还lock(...)
可以使用主循环来防止重入。
回答by PEZ
Have you checked the error logs? Maybe you run out of timers somehow. Maybe you can create just one timer when you initialize the ArchiveService and skip the OnStart stuff.
你检查过错误日志吗?也许你以某种方式用完了计时器。也许您可以在初始化 ArchiveService 时只创建一个计时器并跳过 OnStart 内容。
回答by StingyHyman
I have seen this before with both timer, and looped services. Usually the case is that an exception is caught that stops the timer or looping thread, but does not restart it as part of the exception recovery.
我之前在计时器和循环服务中都看到过这一点。通常的情况是,捕获到的异常会停止计时器或循环线程,但不会作为异常恢复的一部分重新启动它。
To your other points... I dont think that there is anything "elegant" about the timer. For me its more straight forward to see a looping operation in code than timer methods. But Elegance is subjective.
对于您的其他观点......我不认为计时器有任何“优雅”之处。对我来说,在代码中看到循环操作比定时器方法更直接。但优雅是主观的。
Memory issue? Not if you write it properly. Maybe a processor burden if your Thread.Sleep() isn't set right.
内存问题?如果你写得好,就不会。如果您的 Thread.Sleep() 设置不正确,可能会给处理器带来负担。
回答by Stefan
I have made exactly the same as you in a few projects but have not had the problem.
我在一些项目中做了与你完全相同的事情,但没有遇到问题。
Do you have code in the tickTac_Elapsed that can be causing this? Like a loop that never ends or some error that stops the timer, using threads and waiting for ending of those and so on?
您在 tickTac_Elapsed 中有可能导致此问题的代码吗?就像一个永远不会结束的循环或一些停止计时器的错误,使用线程并等待那些结束等等?
回答by Marc Gravell
Interesting issue. If it is truly just time related (i.e. not an exception), then I wonder if you can simply periodically recycle the timer - i.e.
有趣的问题。如果它真的只是时间相关(即不是例外),那么我想知道您是否可以简单地定期回收计时器 - 即
private void tickTack_Elapsed(object sender, ElapsedEventArgs e)
{
CheckForRecycle();
// ... actual code
}
private void CheckForRecycle()
{
lock(someLock) {
if(++tickCount > MAX_TICKS) {
tickCount = 0;
tickTack.Stop();
// re-create timer
tickTack = new Timer(...);
tickTack.Elapsed += ...
tickTack.Start();
}
}
}
You could probably merge chunks of this with the OnStart
/ OnStop
etc to reduce duplication.
您可能可以将这些内容与OnStart
/ OnStop
etc合并以减少重复。
回答by Steven A. Lowe
unhandled exceptions in timers are swallowed, and they silently kill the timer
定时器中未处理的异常被吞了,它们默默地杀死了定时器
wrap the body of your timer code in a try-catch block
将计时器代码的主体包装在 try-catch 块中
回答by jro
http://support.microsoft.com/kb/842793
http://support.microsoft.com/kb/842793
This is a known bug that has resurfaced in the Framework more than once.
这是一个已知的错误,在框架中不止一次出现。
The best known work-around: don't use timers. I've rendered this bug ineffective by doing a silly "while (true)" loop.
最著名的解决方法:不要使用计时器。我通过一个愚蠢的“while (true)”循环使这个错误无效。
Your mileage may vary, so verify with your combination of OS/Framework bits.
您的里程可能会有所不同,因此请验证您的操作系统/框架位组合。