Joe*_*own 31 .net service windows-services timer
我有一个用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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我真的在这个问题上摸不着头脑.任何人都可以发现我出错的傻事吗?
编辑:
通过建议,我IntervalTimer.Enabled = true;之前IntervalTimer.Start();在服务OnStart方法中添加.这不能解决问题.
我已经将文件跟踪日志记录添加到服务中以确认一些内部结构,并且我确信在OnStart()完成时Timer.Enabled值为true.
Joe*_*own 48
这是我的解决方法......
经过太多时间寻找答案,我发现了各种各样的文章和博客讨论Windows服务中的计时器.我已经看到了很多关于这方面的意见,它们都分为三类,并按频率降序排列:
不要使用,System.Windows.Forms.Timer因为它不起作用.(这才有意义)
不要使用,System.Threading.Timer因为它不起作用,System.Timers.Timer而是使用.
不要使用,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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我讨厌"医生,医生,当我这样做时疼痛......"解决方案,但这就是我不得不诉诸的.对于有这个问题的下一个人来说还有一个意见...
Mic*_*aga 10
您忘记通过设置启用计时器:
IntervalTimer.Enabled = true;
Run Code Online (Sandbox Code Playgroud)
或调用Start方法:
IntervalTimer.Start();
Run Code Online (Sandbox Code Playgroud)
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();
}
Run Code Online (Sandbox Code Playgroud)
小智 6
显然,System.Timers.Timer会隐藏任何异常,悄悄地吞下它们,然后窒息.当然,您可以在您已添加为计时器的处理程序的方法中处理这些,但是如果在入口处立即抛出异常(在执行第一行代码之前,如果您的方法声明了变量,则会发生这种情况)例如,如果你在一个强名称的DLL中使用了一个你有错误版本的对象,那么你永远不会看到那个异常.
你要和我们一起撕裂你的头发.
或者你可以这样做:
(我最终停止了计时器,因为如果它失败了,再次尝试对这个特定的应用程序没有任何意义......)
希望这能帮助那些从Google登陆的人(就像我一样).
我还必须切换到 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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我希望这个能帮上忙!