我有一个用C#编写的Windows服务,用于每隔几分钟执行一次任务。 我正在使用System.Timers.Timer ,但它似乎永远不会出现。 我已经在SO和其他地方查看了很多不同的帖子,我没看到我的代码出了什么问题。

这是我的代码,为清楚起见删除了与非计时器相关的项目...

namespace NovaNotificationService
{
    public partial class NovaNotificationService : ServiceBase
    {
        private System.Timers.Timer IntervalTimer;
        public NovaNotificationService()
        {
            InitializeComponent();
            IntervalTimer = new System.Timers.Timer(60000);  // Default in case app.config is silent.
            IntervalTimer.Enabled = false;
            IntervalTimer.Elapsed += new ElapsedEventHandler(this.IntervalTimer_Elapsed);
        }

        protected override void OnStart(string[] args)
        {
            // Set up the timer...
            IntervalTimer.Enabled = false;
            IntervalTimer.Interval = Properties.Settings.Default.PollingFreqInSec * 1000;
            // Start the timer and wait for the next work to be released...
            IntervalTimer.Start();
        }

        protected override void OnStop()
        {
            IntervalTimer.Enabled = false;
        }

        private void IntervalTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {   // Do the thing that needs doing every few minutes...
            DoWork();
        }
    }
}

我真的在这个问题上摸不着头脑。 任何人都可以发现我出错的傻事吗?

编辑:根据建议,我添加了IntervalTimer.Enabled = true; IntervalTimer.Start();之前IntervalTimer.Start(); 在服务OnStart方法中。 这不能解决问题。

我已经将文件跟踪日志记录添加到服务中以确认一些内部结构,并且我确信在OnStart()完成时Timer.Enabled值为true。

===============>>#1 票数:48 已采纳

这是我的解决方法......

经过太多时间寻找答案,我发现了各种各样的文章和博客讨论Windows服务中的计时器。 我已经看到了很多关于这方面的意见,它们都分为三类,并按频率降序排列:

  1. 不要使用System.Windows.Forms.Timer因为它不起作用。 (这才有意义)

  2. 不要使用System.Threading.Timer因为它不起作用,请改用System.Timers.Timer

  3. 不要使用System.Timers.Timer因为它不起作用,请改用System.Threading.Timer

基于此,我尝试了2.这也是微软推荐的方法,因为他们说System.Timers.Timer 适合“服务器应用程序”

我发现System.Timers.Timer在我的Windows服务应用程序中不起作用。 因此我切换到System.Threading.Timer 这是一个麻烦,因为它需要一些重构才能使它工作。

这大约是我现在的工作代码...

namespace NovaNotificationService
{
    public partial class NovaNotificationService : ServiceBase
    {
        private System.Threading.Timer IntervalTimer;
        public NovaNotificationService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            TimeSpan tsInterval = new TimeSpan(0, 0, Properties.Settings.Default.PollingFreqInSec);
            IntervalTimer = new System.Threading.Timer(
                new System.Threading.TimerCallback(IntervalTimer_Elapsed)
                , null, tsInterval, tsInterval);
        }

        protected override void OnStop()
        {
            IntervalTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            IntervalTimer.Dispose();
            IntervalTimer = null;
        }

        private void IntervalTimer_Elapsed(object state)
        {   // Do the thing that needs doing every few minutes...
            // (Omitted for simplicity is sentinel logic to prevent re-entering
            //  DoWork() if the previous "tick" has for some reason not completed.)
            DoWork();
        }
    }
}

我讨厌“医生,医生,当我这样做时疼痛......”解决方案,但这就是我不得不诉诸的。 对于有这个问题的下一个人来说还有一个意见...

===============>>#2 票数:10

您忘记通过设置启用计时器

IntervalTimer.Enabled = true;

或者调用Start方法

IntervalTimer.Start();
protected override void OnStart(string[] args)
{
    // Set up the timer...
    IntervalTimer.Interval = Properties.Settings.Default.PollingFreqInSec * 1000;
    // Start the timer and wait for the next work to be released...
    IntervalTimer.Start();
}

===============>>#3 票数:5

显然,System.Timers.Timer会隐藏任何异常,悄悄地吞下它们,然后窒息。 当然,你可以在你作为处理程序添加到你的计时器的方法中处理这些,但是如果在入口处立即抛出异常(在第一行代码执行之前,如果你的方法声明了一个变量,就会发生这种情况)例如,如果你在一个强名称的DLL中使用了一个你有错误版本的对象,那么你永远不会看到那个异常。

你要和我们一起撕裂你的头发。

或者你可以这样做:

  • 创建一个包装器方法(在try-catch循环中)调用您想要执行的方法。 如果这个方法在你身上濒临死亡,那么被包装的方法可以在不杀死计时器的情况下进行异常处理,因为如果你不停止计时器,它就不会发现出现问题。

(我最终停止了计时器,因为如果它失败了,再次尝试对于这个特定的应用程序没有任何意义......)

希望这能帮助那些从Google登陆的人(就像我一样)。

===============>>#4 票数:4

我还必须切换到System.Threading.Timer。 为了使重新分解更容易,其他人更容易实现,我创建了一个单独的类,包含System.Threading.Timer的实例,并且具有与System.Timers.Timer几乎相同的方法,因此调用代码只需要很少的更改:

/// <summary>
/// Custom Timer class, that is actually a wrapper over System.Threading.Timer
/// </summary>
/// <seealso cref="System.IDisposable" />
internal class Timer : IDisposable
{
    System.Threading.Timer _timer;

    public Timer()
    {

    }
    public Timer(int interval) : this()
    {
        this.Interval = interval;
    }

    public bool AutoReset { get; set; }
    public bool Enabled { get; set; }
    public int Interval { get; set; }
    public Action<object> OnTimer { get; internal set; }

    public void Dispose()
    {
        if (_timer != null)
        {
            _timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            _timer.Dispose();
            _timer = null;
        }
    }

    public void Start()
    {
        _timer = new System.Threading.Timer(
            new System.Threading.TimerCallback(OnTimer), null, 0, Interval);
    }
    public void Stop()
    {
        if (_timer != null)
        {
            _timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
        }
    }
}

我希望这个能帮上忙!

===============>>#5 票数:3

要添加到“user1820848”写的内容,因为这也是我的问题,如果您的System.timers.timer elapsed事件似乎没有被触发,请将事件处理程序中的所有内容放在try / catch块中,并查找那里有什么问题。 我尝试了所有推荐的方法来处理这个问题(或者我认为),包括从system.timers.timer切换到system.threading.timer,这也没有用。

我认为这个问题很复杂,因为我们很多人正在将我们的应用程序从我们的工作站移动到我们没有任何调试支持的服务器上,我们可以将其连接到正在运行的服务并验证它是否正常工作。 因此,您会遇到事件日志消息或tracelistener消息,并且事件不会触发是完全奇怪的。

我有一种情况,我在这台服务器上有三个运行服务,运行基本相同的计时器代码。 我甚至一行一行地使用另一个运行服务的代码,以确保我正在处理system.timers.timer。 但是其他服务工作正常,而且这个似乎根本没有解雇这个事件。

事实证明,问题在于,在我最初的昏暗语句中,我正在尝试连接到Oracle的类。 该调用失败了,但实际上失败了,因为我的工作站和服务器上的Oracle客户端版本略有不同。 它发生在CLR解析引用时,所以它没有被我的底层类try / catch块捕获。 如果我正在调试,调试器会标记错误。 在服务器上运行,CLR无法告诉我有关该问题的信息。 所以我的服务只是坐在那里没有发现错误。

所有内容放入try / catch中会立即指出问题所在。 在该子例程中的任何声明之前尝试。 如果你在早期的声明中失败了,那就是你将如何发现它。

[对不起,单独的答案,但你必须提供答案,以获得足够的声誉,甚至评论别人的答案?!?]

[编辑:要尝试的另一件事是将您的代码从计时器事件中取出,将其放入另一个子/函数,从您的启动代码中调用它,并将函数调用放入您的计时器事件中。 几周后,回到我的工作站,尝试运行相同的代码,我有那种下沉的感觉,我的计时器事件没有被调用,我以前来过这里。 确实! 但是把所有东西放在try / catch中也不起作用!?! 将它移动到函数调用和Bam,我的异常 - 再次是Oracle。 但是在try / catch中的每一行都没有出现,直到我将代码移出timer事件并再次尝试。

===============>>#6 票数:-2

 private void IntervalTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {   // Do the thing that needs doing every few minutes...
        DoWork();

        //Add following 2 lines. It will work.
        **IntervalTimer.Interval= 100; //any value
        IntervalTimer.Start();**
    }

  ask by Joel Brown translate from so

未解决问题?本站智能推荐:

6回复

在Windows服务中使用Timer

我有一个Windows服务,我想在每10秒钟创建一个文件。 我得到了很多评论,Windows服务中的Timer将是最好的选择。 我怎样才能做到这一点?
2回复

Windows Service无法及时启动-将初始工作负荷传递给计时器吗?

我正在运行Windows服务,该服务执行大型数据迁移过程(首次运行将花费10分钟以上)。 目前,我的服务最初在启动时运行一次,然后每4小时运行一次。 像这样(摘录): 问题是在部署和运行后,Windows服务出现错误,提示“服务未及时响应启动或控制请求”。 我意识到我可以从On
1回复

为Windows服务创建数据库驱动的System.Timers.Timer

我试图基于数据库中的参数动态创建System.Timers.Timer。 例如,如果表有5行。 我需要创建5个计时器。 诸如开始时间和间隔之类的参数存储在数据库中。 你该怎么做? 谢谢
2回复

为什么Windows Service不能与System.Timers.Timer或System.Windows.Forms.Timer一起正常工作

我最近遇到了编写Windows服务的挑战。 我需要定期请求URL并检查其可用性。 为此,我决定在服务的OnStart方法中初始化一个计时器,并在timer_Tick事件中完成所有工作。 我的第一种方法是使用System.Windows.Forms.Timer及其Tick事件。 我选择
1回复

Windows Service中的System.Timers.Timer Elapsed事件多次触发

我正在使用带有计时器的Windows服务,以在每个时间间隔安排作业。 似乎计时器经过的事件被触发了不止一次。 这里是一个代码示例: 你能帮助我吗? 谢谢
1回复

C#Windows服务-计时器在调试中不起作用

我已经开始用c#语言构建Windows服务。 我想在其中实现计时器功能。 但是由于某些原因,在调试过程中不会触发DoIt计时器事件处理程序,而且我也没有得到任何异常。 我正在尝试使用Debug-> Start new instance调试Windows服务。 行TraceLog
1回复

Windows Service Tick ElapsedEventArgs从未被调用

我试图部署一项在生产服务器本地运行良好的服务。 但是在此服务器上,ElapsedEventHandler似乎从未调用我的方法Tick() 我已经阅读了与“其他Windows服务”类似的其他线程-计时器似乎未打勾或Windows服务 中未调用计时器打勾事件,但我对我的问题没有任何答案:/
2回复

如何只触发一次System.Timers.Timer

我正在创建一个WindowsService,它有一个Timer绑定到一个具有无限循环的EventHandler; 我希望能够在服务的OnStart()方法中触发此Timer一次,然后在服务的OnStop()中停止Timer。 如何强制定时器仅触发一次? 另外,这是控制WindowsSe
2回复

.net3.5 System.Timers.Timer.Elapsed两次

我正在为Windows服务项目编码,我使用System.Timers.Timer进行一些工作。 我将间隔设置为2000毫秒。 但是我发现计时器会在前2000毫秒内将Elapsed事件引发1次,然后每隔2000毫秒将Elasped事件引发两次。 我认为我的程序有问题,我尝试通过锁
1回复

计时器不在Windows Service中触发,但在控制台应用程序中触发

我试图在Windows服务中使用计时器,我安装了该服务并在服务中启动它,但计时器不会触发。 但是,当我在控制台应用程序中使用完全相同的代码时,计时器就会触发。 我尝试了很多不同的建议,但这些建议似乎都不在Windows服务中对我有用 这是我的代码... } 我只是不明白为