c# – 是否可以将异步事件处理程序附加到System.Timers.Timer?

前端之家收集整理的这篇文章主要介绍了c# – 是否可以将异步事件处理程序附加到System.Timers.Timer?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经阅读过SO here文章 here
我有一个计时器事件,每隔一段时间触发一次,我想在处理程序内部进行一些异步处理,所以有类似的事情:
Timer timer = new Timer();
        timer.Interval = 1000;
        timer.Elapsed += timer_Elapsed; // Please ignore this line. But some answers already given based on this line so I will leave it as it is.
        timer.Elapsed += async (sender,arguments) => await timer_Elapsed(sender,arguments);


       private async Task timer_Elapsed(object sender,ElapsedEventArgs e)
       {
          await Task.Delay(10);
       }

上面的代码编译和工作.

但我不确定为什么代码正在编译. ElapsedEventHandler预期的签名是

void timer_Elapsed(object sender,ElapsedEventArgs e)

但是我的方法返回Task而不是void,因为不建议使用async void.但这与ElapsedEventHandler签名不匹配,并且仍然在编译&工作?

可以在Timer.Elapsed上调用asyn方法吗?代码将在windows服务中执行.

更新1

async void is “not recommended”,with one very important exception:
event handlers.

它的异步事件处理程序或同步事件处理程序是否重要?

MSDN文章herecsays

Void-returning async methods have a specific purpose: to make
asynchronous event handlers possible.

Timer.Elapsed是我认为同步事件处理程序我还能将async void附加到它吗?

解决方法

async void是“不推荐”的,有一个非常重要的例外:事件处理程序.

你的代码编译得很好(第二个事件订阅……第一个会生成编译时错误,假设两个语句中都有相同的timer_Elapsed()方法),因为编译器可以推断委托的返回类型应该是无效的.异步匿名方法也可以返回Task,但在这种情况下,这将是错误方法签名,因此您将获得void.

将事件句柄声明为async void也没关系:

private async void timer_Elapsed(object sender,ElapsedEventArgs e)
   {
      await Task.Delay(10);
   }

使用如下:

timer.Elapsed += timer_Elapsed;

对异步方法返回void并不理想,但在事件处理程序的情况下,没有代码将继续使用Task(除非事件是专门用于理解异步方法,如Asynchronous events in C#).如果您从这样做中获得零利益,那么没有理由向后弯腰以遵守原本正确的编码实践.

另见Should I avoid ‘async void’ event handlers?

附录:

从您的编辑到问题:

Timer.Elapsed is I think synchronous event handler can I still attach async void to it?

它不是异步或同步的事件,而是处理程序本身.这完全取决于您是否使用async并等待处理程序方法.您可以,如您的问题和我的答案中所述,使用带有Elapsed事件的异步void处理程序方法,就像您可以使用任何其他事件一样(假设事件签名需要void作为处理程序返回类型,这当然是标准对于传统的.NET事件).

猜你在找的C#相关文章