我在IIS中托管了一个WCF服务。我不时地需要清理内部结构,并希望每小时都有一个计时器。
我运行此语句来设置计时器:
using System.Threading;
...
...
_timerMisc = new Timer(timerMisc_OnTimer, new object(), Timeout.Infinite, 60 * 60 * 1000);
private void timerMisc_OnTimer(object state)
{
DoStuff();
}
计时器永远不会开始。我错过了什么?这是否可能在IIS托管的WCF服务上?
答案 0 :(得分:4)
不建议在IIS托管环境中运行计时器或任何计划机制,因为应用程序会不时被回收。
设置Timeout.Infinite将阻止您的计时器启动。如果要立即启动它,请将其设置为0。希望它有所帮助。
答案 1 :(得分:0)
虽然我同意在IIS托管的WCF服务中使用长时间运行的计时器并不可靠,但从IIS托管的WCF服务中作为临时解决方案运行短期计时器操作会很有用。
在服务操作期间启动计时器,使其具有正确的上下文,而不是从构造函数启动计时器。 SynchronizationContext.Current在服务操作期间可用,但在构造期间不可用。确保设置一个全局标志以指示计时器是否已启动以确保它不会多次启动。
该解决方案仅在满足以下条件时才有效:
服务的InstanceContextMode:= InstanceContextMode.Single。我碰巧使用ConcurrencyMode:= ConcurrencyMode.Multiple,但该设置可能不会影响计时器。
在启动计时器的服务操作将在服务的生命周期的早期调用,并且在调用任何服务操作之前不需要运行计时器,因此建议将定时操作移至单独的不断运行的应用程序,然后从那里执行服务操作。
如果这些警告与您的解决方案不矛盾,这里有一个例子:
Public Function ServiceOperationA(Data As Object) As Object Implements IService.ServiceOperationA
ActivateTimers_SyncContextRequired()
'Other operation actions...'
End Function
Private TimersActivated_SyncContextPresent As Boolean = False
Private ReadOnly ActivatingTimers_SyncContextPresent As New Object
Friend Sub ActivateTimers_SyncContextRequired()
Dim ExitSub As Boolean = False
SyncLock ActivatingTimers_SyncContextPresent
If TimersActivated_SyncContextPresent Then ExitSub = True
TimersActivated_SyncContextPresent = True
End SyncLock
If ExitSub Then Exit Sub
TimersActivated_SyncContextRequired = True
timerCheckData = New System.Timers.Timer(TimeSpan.FromSeconds(10).TotalMilliseconds)
timerCheckData.AutoReset = True
AddHandler timerCheckData.Elapsed, AddressOf timerCheckData_Elapsed
timerCheckData.Start()
End Sub
Friend Sub timerCheckData_Elapsed()
'Timed operations...'
End Sub
我打算将定时功能移到Windows服务或ASP.Net + Hangfire:www.hangfire.io,然后从那里执行定时服务操作;您也可以在Windows服务而不是IIS中托管您的WCF服务,或者在最符合您需求的情况下使用SignalR。