System.Threading.Timer一段时间后没有触发

时间:2010-09-03 12:47:26

标签: c# .net .net-4.0 timer

我有一个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,它正在运行,没有任何问题。

5 个答案:

答案 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之后使用allTask​​sWaitHandle.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);


    }
    }
}