“异步任务然后等待任务”与“任务然后返回任务”[重复]

Posted

技术标签:

【中文标题】“异步任务然后等待任务”与“任务然后返回任务”[重复]【英文标题】:"async Task then await Task" vs "Task then return task" [duplicate] 【发布时间】:2016-10-27 06:53:09 【问题描述】:

快速提问..

为了对异步编程和await有一些扎实的基础了解,我想知道这两个代码sn-ps在多线程以及执行顺序和时间方面有什么区别:

这个

public Task CloseApp()

        return Task.Run(
                         ()=> 
                                // save database
                                // turn off some lights
                                // shutdown application
                          );

对比:

public async Task CloseApp()

        await Task.Run(
                         ()=> 
                                // save database
                                // turn off some lights
                                // shutdown application
                          );

如果我在这个例程中调用它:

private async void closeButtonTask()

    // Some Task 1
    // ..

    await CloseApp();

    // Some Task 2
    // ..

【问题讨论】:

它们在异常的包装方式上有细微的差别 可能被骗***.com/questions/21033150/… closeButtonTask 应该返回 Task 而不是 void。 我整理的这个sharplab sample 显示了底层机制。 【参考方案1】:

几乎相同(在线程等方面)。但是对于第二个(使用await),编译器会产生更多的开销。

声明为async 并使用await 的方法被编译器转换为状态机。因此,当您点击await 时,控制流将返回到调用方法,并在等待的Task 完成后,在await 之后恢复您的async 方法的执行。

由于await 之后没有更多代码,因此无论如何都不需要使用await。只需返回Task 就足够了。

【讨论】:

"当你点击 await 时,控制流返回给调用方法" -- 控制流可能返回给调用方法,特别是当等待的任务已经完成时它不会返回。 @acelent 非常感谢细节,从没想过任务完成后会发生什么。我不知道编译器逐行执行的具体细节。 我完全不明白 当您的任务完成时,线程池中的一个线程将调用Post 方法并通知调用者任务已完成。我记得其余的异步方法将作为ContinueWith 执行。执行将从等待点继续,但可以在不同的线程中执行。 这篇博文解释得很清楚。 devblogs.microsoft.com/premier-developer/…总之有一些优化逻辑,防止不必要的等待。【参考方案2】:

这两种方法之间几乎没有区别。基本上,它们共享相同的语义。但是,带有 async/await 的版本将内部任务的执行包装在外部编译器生成的任务中。非异步版本没有。因此,非异步版本(非常轻微地)更有效。

【讨论】:

“非异步版本(非常轻微地)更有效。” -- 这取决于,如果该方法被非常频繁地调用,那么异步/等待版本可能产生明显的垃圾:状态机和另一个任务。 @acelent:产生一些第 0 代垃圾对我来说仍然感觉很边缘 好的,我只是想指出,并非所有人都这样 (1),而且你不能依赖任务或对任务的引用是那么短暂的 (2 , at 0:25:40, at 0:30:20)。

以上是关于“异步任务然后等待任务”与“任务然后返回任务”[重复]的主要内容,如果未能解决你的问题,请参考以下文章

3.管道符重定向与环境变量

链接脚本与重定位

链接脚本与重定位

请问重定向与请求转发有啥区别?

Linux管道符重定向与环境变量

管道与重定向(有重定向习题未做)