在 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 事件处理程序中使用异步等待的主要内容,如果未能解决你的问题,请参考以下文章