我有一个Windows服务应用程序。并通过在控制台模式下运行来调试它。
此处http://support.microsoft.com/kb/842793 据说Timers.Timer有一个bug而不是在Windows服务中触发。解决方法是使用Threading.Timer 本文适用于.NET 1.0和1.1
我使用的是.NET 4,但经过一段时间Threading.Timer也没有开火。那可能是什么原因呢? 您可以建议什么作为解决方法?
谢谢,
最好的问候
编辑:我将计时器从Threading.Timer更改为Timers.Timer,它正在运行,没有任何问题。
答案 0 :(得分:51)
你是否在某个地方保留了对你的计时器的引用,以防止它被垃圾收集?
来自the docs:
只要您使用计时器,就可以了 必须保持对它的引用。和。一样 任何托管对象,Timer都是主题 到有垃圾收集的时候 没有引用它。一个事实,一个 定时器仍处于活动状态并不会阻止 它被收集起来。
答案 1 :(得分:11)
您的计时器对象超出范围并在一段时间后被垃圾收集器删除,这会阻止回调被触发。
在班级成员中保存对它的引用。
答案 2 :(得分:6)
解决?
就我个人而言,我建议使用RegisterWaitForSingleObject函数而不是计时器,因为你遇到了完全的原因。 RegisterWaitForSingleObject注册一个委托,该委托将在您设置为计时器的时间间隔内被调用,并且 super 易于实现。您可以在几小时内启动并运行测试装置。我在Windows服务中使用这种间隔触发方法,它是一个经过验证的稳定解决方案,对我有用。
阅读以下链接,并转到文章中的链接,了解代码示例和演练。
使用Windows服务在.NET中运行定期进程:
http://allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html
答案 3 :(得分:2)
以下是如何使用RegisterWaitForSingleObject:
当你有代码注册这样的计时器时:
const int scheduledPeriodMilliseconds = 20000;
new Timer(ServiceBusTimerCallback, parameters, 0, scheduledPeriodMilliseconds);
private static void ServiceBusTimerCallback(object params)
{
}
你可以拥有:
const int scheduledPeriodMilliseconds = 20000;
var allTasksWaitHandle = new AutoResetEvent(true);
ThreadPool.RegisterWaitForSingleObject(
allTasksWaitHandle,
(s, b) => { ServiceBusTimerCallback(parameters); },
null,
scheduledPeriodMilliseconds,
false);
您可以在ServiceBusTimerCallback之后使用allTasksWaitHandle.Set()来通知用户任务已完成,因此它将立即再次运行任务。上面发布的代码将在timeont通过后运行任务,所以每20秒。
我在WebAPI项目中实现了它,效果很好。
答案 4 :(得分:0)
使用企业库进行日志记录和重复线程的Windows服务的完整示例。如果不使用entreprise库,则删除logger.write行
namespace Example.Name.Space
{
public partial class SmsServices : ServiceBase
{
private static String _state = "";
private ManualResetEvent _stop = new ManualResetEvent(false);
private static RegisteredWaitHandle _registeredWait;
public WindowsServices()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Logger.Write("Starting service", LoggerCategory.Information);
_stop.Reset();
_registeredWait = ThreadPool.RegisterWaitForSingleObject(_stop,
PeriodicProcess, null, 5000, false);
}
protected override void OnStop()
{
// UpdateTimer.Stop();
_stop.Set();
Logger.Write("Stopping service", LoggerCategory.Information);
}
private static void PeriodicProcess(object state, bool timedOut)
{
if (timedOut)
{
// Periodic processing here
Logger.Write("Asserting thread state", LoggerCategory.Debug);
lock (_state)
{
if (_state.Equals("RUNNING"))
{
Logger.Write("Thread already running", LoggerCategory.Debug);
return;
}
Logger.Write("Starting thread", LoggerCategory.Debug);
_state = "RUNNING";
}
Logger.Write("Processing all messages", LoggerCategory.Information);
//Do something
lock (_state)
{
Logger.Write("Stopping thread", LoggerCategory.Debug);
_state = "STOPPED";
}
}
else
// Stop any more events coming along
_registeredWait.Unregister(null);
}
}
}