C# 在高效的 Windows 服务中安排重复任务的最佳方法

Posted

技术标签:

【中文标题】C# 在高效的 Windows 服务中安排重复任务的最佳方法【英文标题】:C# Best way to schedule recurring task in an efficient windows service 【发布时间】:2017-01-27 01:06:56 【问题描述】:

我在 .Net Framework 4.0 中编写了一个 Windows 服务,我需要在其中安排一个重复性任务。新任务只有在前一个任务完成后才能运行,所以没有并行任务...... 我所有的任务都在同一个对象(WCF 通道工厂)上工作。 一项任务几乎需要 2 秒才能完成,并且可能每 2 秒或每小时安排一次。 我的限制是让这个 Windows 服务在内存和处理器使用的角度上尽可能不可见/不可见......

我已经找到了这两种方法:

使用System.Timers.TimerAutoreset 为假=> 我必须 实现ElapsedEventHandler 并传递我的共享对象(WCF 渠道工厂) 使用永无止境的循环:不确定 mem/proc 在 该状态,但没有线程方面需要处理。

有什么建议吗?

谢谢,祝你有美好的一天!

【问题讨论】:

这是我使用 TPL 实现重复任务的一种方式。它可能会给你另一个想法/路线。 ***.com/q/39457595/2985796 【参考方案1】:

对我来说很好:我启动了一次计时器,然后在 Tick 方法中我将安排下一个 Tick 调用。像这样:

private Timer _timer;

//Interval in milliseconds
int _interval = 1000;

public void SetTimer()
   
    // this is System.Threading.Timer, of course
    _timer = new Timer(Tick, null, _interval, Timeout.Infinite);


private void Tick(object state)

    try
    
        // Put your code in here
       
    finally
    
        _timer?.Change(_interval, Timeout.Infinite);
    


// dont forget to dispose your timer using await _timer.DisposeAsync(); or _timer.Dispose();

【讨论】:

谢谢 Tym,我想我应该有 new System.Threading.Timer(Tick, MyWCFSharedObject, _interval, Timeout.Infinite) ... 如果可以,我希望对我在 Tick 方法中的 MyWCFSharedObject 将在 Windows 服务级别可见? 勾选 - 只是函数,你可以让它在一级可见,如果你真的需要,你可以将它设为公共静态。 实际上,作为我使用它的示例,github.com/tym32167/arma3beclient/blob/develop/src/… 好的,知道了!谢谢!我尝试您的解决方案并返回验证此答案。 @Francois 不。在我的解决方案中,不可能同时在不同的线程中运行 Tick。【参考方案2】:

System.Timers.Timer 是可行的方法,对系统性能几乎没有影响。当前系统可以处理数千个计时器。

由于您希望计时器继续运行,请不要设置 AutoReset,但您需要一种方法来更改其间隔(如果您需要的话)。

您的服务实例应该包含您的 WCF 通道工厂的实例。

为确保同步处理,您应该实现一个Interlocked 受保护标志,就像一个long,它可以作为忙碌的指示器。例如,如果等于 1,则从计时器经过事件开始处理的方法将简单地返回。一旦处理完成,此时您将标志设置为零,更多的计时器经过事件将能够进入并再次开始处理。

请记住在各种服务事件中停止、重新启动和处置计时器,例如暂停、停止、启动。

【讨论】:

有趣。当然,我的 WCF 通道工厂对象是在 Windows 服务级别定义的。我同意您在不使用 AutoReset 的情况下提出的建议,这是另一种处理方式。但我不明白为什么我需要联锁处理,因为在我的情况下不会发生并行任务? 我认为在这个解决方案中你必须使用 Interlocked 因为当你读取这个标志时,另一个线程能够写入它。如果您必须在一个线程中写入内存并从另一个线程中读取它,您应该使用线程安全结构。互锁有利于线程安全地读取/写入该标志。 好吧...我只是认为我可能在我的 Windows 服务的 OnStop() 或 OnSessionChanged() 方法中有并发内存访问...我已经阅读了一些黑暗点关于联锁,所以我想避免它们...... :) System.Timers.Timer 基于 System.Threading.Timer 而Elapsed 发生在 ThreadPool 线程上,因此不在主线程上。因此在使用计时器时需要线程安全。 感谢 DvS 的澄清!

以上是关于C# 在高效的 Windows 服务中安排重复任务的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

在 Windows Server 2008 R2 中安排任务

如何在 Django 中安排任务?

在后台任务中安排通知

如何在 Windows Phone 应用程序 8.1 rt 中安排本地通知?

使用定期任务在 C# 中构建 Windows 服务 [重复]

如何在 Windows 8 应用程序中安排特定日期和时间的 toast 通知?