Windows 服务(通过 webHttpBinding)托管的 WCF Singleton 内的计时器意外终止
我有一个 WCF 服务托管在 Windows 服务中(在本地系统下运行)。我正在其中运行 System.Timer。初始化计时器的操作 o1 是通过 webHttpBinding 通过 http 端点声明的。 我启用了 System.ServiceModel 的跟踪,并从 .svcLog 文件中检查了操作 o1 的侦听持续时间。它表明,运行大约 20 小时后,http 端点处的监听停止了。
我认为这是因为没有传入消息到达该端点。这里的问题是随着监听停止,我的计时器(在特定操作o1内初始化)也停止了!
是否有推荐的方法来保持监听器和计时器长时间运行? 我们可以定期 ping o1 操作以将其保留在内存中吗?
另外,我在操作 o1 中初始化的计时器变量是一个实例变量,即使侦听器关闭,这个变量是否也应该位于内存中(WCF 是单例)?
非常感谢。
代码摘录-
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class SchedulerWindows : ISchedulerWindows
{
///.........all instance variables.....
DataTimer timer = null; /**DataTimer wraps a System.Timers timer variable**/
public List<DataTimer> timersInService = new List<DataTimer>();
public ISchedulerWindows.o1(string s1, string s2, /*********/)
{
//..........//
timer = new DataTimer();
}
}
public class DataTimer
{
/****Newly introduced System.Threading.Timer, previously I was using System.Timers.Timer which was dying****/
public System.Threading.Timer thTimer;
private static readonly object dbAccessLock = new object();
private static readonly object thCallbackLock = new object();
public DataTimer()
{
}
public DataTimer(/************/)
{
TimerCallback timerDelegate = new TimerCallback(this.WorkMethod);
EventLogLogger l = new EventLogLogger();
//l.LogMessage("setting up timer ");
thTimer = new Timer(this.WorkMethod, null, 0, period);
}
...
}
编辑:从 System.Timers 命名空间更改为 System.Threading 命名空间并增加定时间隔为我解决了这个问题。计时器变量不再消失。
I have a WCF service hosted in a Windows Service (running under Local System). I am running a System.Timer inside it. The Operation o1, that initializes the Timer, is declared over a http endpoint over webHttpBinding.
I enabled tracing for System.ServiceModel and from the .svcLog file I checked the Listen Duration for the Operation o1. It shows that, after running for approx 20 hours the Listening at the http endpoint just stops.
I think the this due to the fact that no incoming message arrived at that endpoint. The issue here is with the Listening coming to a stop, my timer(which was initialized inside that particular Operation o1) also stops!
Is there a recommended way to keep the Listener, and hence the timer, up for long durations?
Can we periodically ping the o1 Operation to keep it in memory?
Also, my timer variable that I initialize inside the Operation o1 is an instance variable, isn't this variable expected to be in memory (the WCF being a Singleton) even if the Listener closes??
Thanks so much.
Code Exceprts-
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class SchedulerWindows : ISchedulerWindows
{
///.........all instance variables.....
DataTimer timer = null; /**DataTimer wraps a System.Timers timer variable**/
public List<DataTimer> timersInService = new List<DataTimer>();
public ISchedulerWindows.o1(string s1, string s2, /*********/)
{
//..........//
timer = new DataTimer();
}
}
public class DataTimer
{
/****Newly introduced System.Threading.Timer, previously I was using System.Timers.Timer which was dying****/
public System.Threading.Timer thTimer;
private static readonly object dbAccessLock = new object();
private static readonly object thCallbackLock = new object();
public DataTimer()
{
}
public DataTimer(/************/)
{
TimerCallback timerDelegate = new TimerCallback(this.WorkMethod);
EventLogLogger l = new EventLogLogger();
//l.LogMessage("setting up timer ");
thTimer = new Timer(this.WorkMethod, null, 0, period);
}
...
}
EDIT: Changing to System.Threading namespace from System.Timers namespace AND increasing the timed interval fixed it for me. The timer variable doesn't disappear anymore.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
导致您的问题的最可能原因是 InstanceContextMode。如果您希望服务实例始终位于内存中,则应该使用 Single。您可能有 PerSession 或 PerCall,这可以解释为什么您的计时器消失。您提到您的服务是单例的,但症状非常可疑。服务实例将保留在内存中,直到您关闭主机。
来自 WCF 实例管理:
编辑:当您的侦听器停止侦听且计时器消失时,您可能会检查 Windows 服务是否仍在运行。查看 ServiceHost 本身是否保留在内存中也是有意义的。您还可以在 ServiceHosts 的“Closing”、“Closed”和“Faulted”事件处理程序中添加一些日志记录。
编辑2:
如果你的计时器消失了,那么你应该看看如何分配它。它很可能会被垃圾收集。您必须将其声明为可从活动对象访问的实例字段。使其静态以绝对确定。您为
DataTimer
执行此操作,但不清楚如何在DataTimer
内声明和分配计时器。请发布一些代码。编辑3:
您不应该在操作中创建计时器。如果操作被多次调用会发生什么?老定时器会怎样?我不知道你如何关闭/处置它。您似乎还有两个 DataTimer 构造函数。其中之一什么也不做。最重要的是,你有单独的计时器列表。这有点复杂。请隔离问题,然后也许发布新代码。
The most likely cause for your issue is InstanceContextMode. If you want your service instance to always be in memory you should use Single. You probably have PerSession or PerCall and that would explain why your timer is disappearing. You mention that your service is singleton but the symptoms are very suspicious. The service instance stays in memory until you shutdown host.
From WCF instance management:
EDIT: You probably checked that windows service is still running when your listener stops listening and timer disappears. It would also make sense to see if ServiceHost itself stays in memory. You can also put some logging in ServiceHosts 'Closing', 'Closed' and 'Faulted' event handlers.
EDIT 2:
If your timer is disappearing than you should look at how you allocate it. It most likely gets garbage collected. You have to declare it as an instance field that is reachable from live objects. Make it static to be absolutely sure. You do it for
DataTimer
but it is not clear how the timer is declared and allocated insideDataTimer
. Post some code please.EDIT 3:
You should not create timers in the operation. What happens if operation get called more than once? What happens to the old timer? I don't see how you close/dispose it. You also seem to have two constructors for DataTimer. One of them is doing nothing. And on top of that you have separate list of timers. This is a bit convoluted. Please isolate the problem and maybe post new code after that.
我没有专门遇到这个问题 - 但是,如果您只想在服务运行时运行计时器,为什么不将其设为静态。那么您的实例上下文模式和实例生命周期将不会影响您的功能。
I've not come across this issue specifically - however, if you just want the timer running while the service is running why not make it static. Then your instance context mode and instance lifetime won't affect your functionality.