Windows 服务应用程序挂起
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5288203/
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
Windows Service application hangs
提问by serb
Background:
- Running Window Server 2008 R2.
- The servers has been patched with all the recent updates.
- Server is running 5 services built in .NET 3.5 and all of these services use timers to check database on repeated basis (mostly every 10 seconds).
- These services are not CPU/RAM intensive.
- Server doesn't have any performace and resources issues or bottlenecks.
背景:
- 运行 Window Server 2008 R2。
- 服务器已用所有最近的更新进行了修补。
- 服务器正在运行 .NET 3.5 中内置的 5 个服务,所有这些服务都使用计时器重复检查数据库(通常每 10 秒一次)。
- 这些服务不是 CPU/RAM 密集型的。
- 服务器没有任何性能和资源问题或瓶颈。
For most of the time, everything works as expected, but from time to time, some (or all) services simply stop working. I'm logging all the app exceptions to file, but there are none when it comes to failure. There is also no error in the event logger and the Services manager treats the services as running. I have to stop the services and start them once again to restore the functionality.
在大多数情况下,一切都按预期工作,但有时,某些(或全部)服务会停止工作。我正在将所有应用程序异常记录到文件中,但在失败时没有。事件记录器中也没有错误,服务管理器将服务视为正在运行。我必须停止服务并再次启动它们以恢复功能。
This behavior is unpredictable, sometimes it takes a week or a month before it stops working. Also, sometimes the services "dies" all together or only some of them at the same time.
这种行为是不可预测的,有时需要一周或一个月才能停止工作。此外,有时服务会全部“死亡”或仅同时“死亡”其中的一部分。
Only thing that crossed my mind is the Timer object. I've been using the System.Timers.Timer and found several forum threads stating it is unreliable as the garbage collector may free the instance. I've tried retaining it using GC.KeepAlive() to no avail. I've followed a few suggestion on moving System.Timers.Timer to System.Threading.Timer but this didn't make any difference either.
我唯一想到的是 Timer 对象。我一直在使用 System.Timers.Timer 并发现几个论坛帖子指出它不可靠,因为垃圾收集器可能会释放实例。我尝试使用 GC.KeepAlive() 保留它但无济于事。我遵循了一些关于将 System.Timers.Timer 移动到 System.Threading.Timer 的建议,但这也没有任何区别。
Right at the moment, I'm desperate to find out the source of this behavior. Is there any known similar issue? How can I debug it when there is not exception raised and the event log is silent too?
目前,我非常想找出这种行为的根源。是否有任何已知的类似问题?当没有引发异常并且事件日志也无提示时,我该如何调试它?
Thank you for any advice that may lead to any solution.
感谢您提供任何可能导致任何解决方案的建议。
UPDATE: Including the bare-boned code of the current state:
更新:包括当前状态的基本代码:
private System.Threading.Timer timerPublish = null;
private bool timerDelegateMethodRunning = false;
protected override void OnStart(string[] args)
{
SetupTimer();
}
protected override void OnStop()
{
if (timerPublish != null)
{
timerPublish.Dispose();
}
}
public void SetupTimer()
{
if (timerPublish != null)
{
timerPublish.Dispose();
}
TimerCallback callbackMethod = new TimerCallback(this.timerPublish_Elapsed);
timerPublish = new System.Threading.Timer(callbackMethod, null, 5000, 5000);
}
void timerPublish_Elapsed(Object stateInfo)
{
if (timerDelegateMethodRunning)
{
return;
}
timerDelegateMethodRunning = true;
try
{
// Processing code here
}
finally
{
timerDelegateMethodRunning = false;
}
}
UPDATE2: Thank you guys for your insights and advices. I'll try to debug the services on the production server once the issue happens again. I'll report back as soon as I have anything new (probably in several weeks).
UPDATE2:谢谢你们的见解和建议。一旦问题再次发生,我将尝试调试生产服务器上的服务。一旦我有任何新东西(可能在几周内),我会立即报告。
回答by jgauffin
Why do you complicate things? :) Just use the Timer.Change()
method to trigger the timer again when you are ready.
你为什么要把事情复杂化?:)Timer.Change()
准备好后,只需使用该方法再次触发计时器即可。
Also know that any uncaught exceptions in the WorkerMethod
willf*ckup your service.
还要知道,任何未捕获的异常WorkerMethod
都会搞砸你的服务。
public class YourService
{
private System.Threading.Timer _timer;
protected override void OnStart(string[] args)
{
//run once in 5 seconds.
_timer = new System.Threading.Timer(WorkerMethod, null, 5000, Timeout.Infinite);
}
protected override void OnStop()
{
if (_timer != null)
{
_timer.Dispose();
_timer = null;
}
}
void WorkerMethod(object state)
{
// Processing code here
_worker.Change(5000, Timeout.Infinite); //Run again in 5 seconds
}
}
Update
更新
I saw that you where using System.Timers.Timer
. The biggest problem with it is that it ignores exceptions. That is, if your code throws an exception and you do not catch it: you will never be aware of that exception. It might very well be your problem.
我看到你在哪里使用System.Timers.Timer
. 它最大的问题是它忽略了异常。也就是说,如果您的代码抛出异常而您没有捕获它:您将永远不会意识到该异常。这很可能是你的问题。
回答by Lex Li
Never draw a conclusion too soon before you know what is the cause of the hangs. There can be various unbelievable factors, but dump analysis or live debugging can tell you the truth,
在您了解挂起的原因之前,切勿过早得出结论。可能有各种令人难以置信的因素,但转储分析或现场调试可以告诉你真相,
http://blogs.msdn.com/b/tess/archive/2006/10/16/net-hang-debugging-walkthrough.aspx
http://blogs.msdn.com/b/tess/archive/2006/10/16/net-hang-debugging-walkthrough.aspx
If you like, you can even open a support case via http://support.microsoft.com
如果您愿意,您甚至可以通过http://support.microsoft.com打开支持案例
回答by Grant Thomas
I might suggest a slightly altered pattern for your service, anyway; where we have a readonly
Timer
, which, after initial assignment, simply gets toggledto run as opposed to the way disposing is occurring at the minute, and also keep our own hard reference to the TimerCallback
. LAstly, we leave the disposing of objects up the to service itself (at least the long term objects we're bothered about).
无论如何,我可能会建议为您的服务稍微改变模式;我们有一个readonly
Timer
,在初始分配后,它只是切换到运行,而不是当时发生的处理方式,并且还保留我们自己对TimerCallback
. 最后,我们将对象的处理留给服务本身(至少是我们担心的长期对象)。
Although this pattern may not be a white rabbit from a hat in your case, I can vouch for the reliability of many services constructed in this manner. Therefore, if problems ensue even after implementation of such then I would be highly confident in saying that what follows // Processing code here
is, in and of itself, problematic.
尽管在您的情况下,这种模式可能不是帽子上的白兔,但我可以保证以这种方式构建的许多服务的可靠性。因此,如果即使在实施后仍然出现问题,那么我将非常有信心地说接下来的事情// Processing code here
本身就是有问题的。
private readonly System.Threading.Timer Timer = null;
private readonly System.Threading.TimerCallback Callback = null;
private readonly int Interval = 5000;
public MyService()
{
Callback = new TimerCallback(this.timerPublish_Elapsed);
Timer = new System.Threading.Timer(Callback, null, Timeout.Infinite, Timeout.Infinite);
}
private void Start()
{
Timer.Change(Timespan.Zero, Interval);
}
private void Stop()
{
Timer.Change(Timeout.Inifinite, Timeout.Inifnite);
}
protected override void OnStart(string[] args)
{
Start();
}
protected override void OnStop()
{
Stop();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if(disposing)
{
if(Timer != null)
Timer.Dispose();
}
}