【发布时间】:2013-12-22 03:32:00
【问题描述】:
阅读 this 博客文章,了解 C#5 的 async/await 的一些陷阱。它在 Gotcha #4 中提到了一些我以前没有想到的非常深刻的东西。
简而言之,它涵盖了一个方法具有两个重载的场景,一个采用Action,另一个采用Func<Task>(例如Task.Run)。这个问题的根源在于 async void 方法应该只用于事件处理程序的论点,然后帖子继续描绘以下场景 - 当像下面这样的 lambda 函数可以编译为两者时,编译器会推断什么Func<Task> 和 Action:
Task.Run(async () => {
await Task.Delay(1000);
});
因为Task.Run 有Task.Run(Func<Task>) 和Task.Run(Action) 的签名,所以异步匿名函数编译成什么类型? async void 还是 Func<Task>?我的直觉是它会编译成async void,纯粹是因为它是非泛型类型,但是C#编译器可能很聪明,并且会优先考虑Func<Task>类型。
另外,有没有办法明确声明我希望使用哪个重载?我知道我可以创建一个Func<Task> 的新实例并在那里传递异步 lambda 函数,但它仍会编译为async void,然后将其传递给Func<Task> 的构造函数。确保将其编译为Func<Task> 的理想方法是什么?
【问题讨论】:
-
微软确实改变了编译器,让它选择
Func<Task>而不是Action,其他条件相同。 AFAIK,Eric Lippert 还没有在他的博客上解决这个问题...... :)
标签: c# async-await c#-5.0 lambda