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

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

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

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

有什么建议吗?

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

【问题讨论】:

标签: c# .net multithreading wcf


【解决方案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 的澄清!
猜你喜欢
  • 1970-01-01
  • 2015-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-30
  • 1970-01-01
  • 1970-01-01
  • 2010-11-11
相关资源
最近更新 更多