在 Windows 服务的 timer_elapsed 事件处理程序中使用异步等待

Posted

技术标签:

【中文标题】在 Windows 服务的 timer_elapsed 事件处理程序中使用异步等待【英文标题】:Using async await inside the timer_elapsed event handler within a windows service 【发布时间】:2014-09-20 08:58:45 【问题描述】:

我在 Windows 服务中有一个计时器,并且在 timer_Elapsed 事件处理程序中调用了一个异步方法:

protected override void OnStart(string[] args)

     timer.Start();    
  

private async void timer_Elapsed(object sender, ElapsedEventArgs e)

    _timer.Stop();
    await DoSomething();          
    _timer.Start();

上面的代码可以吗?首先,我读到 async void 不是一个好主意。其次,为什么我首先需要 timer_Elapsed 方法是异步的?它不像 elapsed 事件处理程序,我们将被多个调用者并行调用。但是,如果我不使方法异步,那么我的逻辑就会中断,因为计时器将在 DoSomething 完成之前启动。

那么,让 timer_Elapsed 异步是正确的方法吗?

【问题讨论】:

从异步组合的角度来看,您所拥有的一切都很好。 async void 是应该避免的,但在您的情况下,您无法真正摆脱它。话虽如此,当您可以将OnStart 更改为async void 并且仅在循环内更改await DoSomething(); await Task.Delay(...); 时,为什么还要使用计时器? @Kirill 感谢您的建议。在循环中使用 Task.Delay 比使用计时器更好吗? 就像await 一样,定时器提供了一种编写异步工作的方法。我的建议源于您已经使用一种方法(即await),那么为什么不坚持使用它而不是混合不同的组合方法呢?不过,这是非常主观的,归根结底,您应该使用自己熟悉的方法。定时器本身并没有什么“错误”。 @KirillShlenskiy 说得通,谢谢。 【参考方案1】:

应避免异步 void;它应该只用于事件处理程序。 Timer.Elapsed 是一个事件处理程序。所以,这里不一定是错的。

timer_Elapsed 方法必须是 async,因为它包含一个 await。这是关键字的工作方式:async 将方法重写为异步状态机,从而启用 await 关键字。

【讨论】:

谢谢@Stephen。有趣的是,今天早上我是从你的博客中了解到异步/等待的,写得真好! blog.stephencleary.com/2012/02/async-and-await.html 我也想知道如何在递归方法中正确使用 async/await:***.com/questions/25007709/… @Maxim:恐怕我不明白你的评论。也许你应该问自己的问题? 有 2 个定时器:System.Timers.Timer 和 System.Threading.Timer。据我了解,第一个有 Elapsed 事件,并且可以有异步事件处理程序。第二个接受回调作为构造函数中的参数。那么那个计时器是怎么回事呢?那个回调也可以是异步无效的吗? @Maxim:当然,它逻辑上是一个事件处理程序。

以上是关于在 Windows 服务的 timer_elapsed 事件处理程序中使用异步等待的主要内容,如果未能解决你的问题,请参考以下文章

在Windows Server中怎么安装DHCP服务

在 WCF 中编写 Windows 服务

windows 服务主进程是啥?

Windows 服务可以使用由另一个 Windows 服务托管的 WCF 服务吗?

Windows部署服务(WDS)

如何在windows下安装多个memcached服务