从异步lambda Action转换为Func <task>?

时间:2017-07-12 12:28:07

标签: c# asynchronous lambda

我们知道async的{​​{1}}等效于Action

因此我们可以写:

Func<Task>

但也可以将其写为Func<Task> func = async () => { Console.WriteLine(@"waiting ..."); await Task.Delay(300).ConfigureAwait(false); Console.WriteLine(@"... finished"); };

Action

这在语法上是正确的。 如何将Action action = async () => { Console.WriteLine(@"waiting ..."); await Task.Delay(300).ConfigureAwait(false); Console.WriteLine(@"... finished"); }; 转换为Action action

2 个答案:

答案 0 :(得分:4)

我认为第二个代码段与async void类似 - 只是匿名。除了WinForms事件处理程序之类的边缘情况之外,你真的不应该使用它们。

编译器为您管理返回的Task并将其放入默认线程池并在某些选定的“已知正常”的SynchroContext上运行continuation ..我不记得其余的..检查异步的血腥细节-void你会发表关于为什么你不应该使用它的文章,除非绝对必要。例如:

请注意异常处理中的示例差异。

Aah,我忘了回答:如果那真的是async void那么你就无法转换。简单地说 - 返回的任务已经消失,你无法获得它。你得到的行动是这样的:

Action action = () => 
{
    Func<Task> yourRealTask = async () =>
    {
        Console.WriteLine(@"waiting ...");
        await Task.Delay(300).ConfigureAwait(false);
        Console.WriteLine(@"... finished");
    };

    // ** some compiler-generated code to register/run the task somewhere
    // ** so it will be handled properly instea of being lost due to not
    // ** returning the Task to the caller

    return;
}

所以,实际上,yourRealTask是无法获得的......运气好的话,你可能会通过反射来解决它的问题,但是......不要这样做。只需使用Func<Task>

答案 1 :(得分:1)

第一种情况将创建一个正常的任务工厂。

第二个将创建一个即发即弃的async-void方法,确实很少使用它。

由于编译器非常简洁,它可以通过单个匿名方法创建,并且由程序员决定他需要哪一个。