这是异步流如何工作

时间:2018-05-18 18:21:51

标签: c# asynchronous async-await

我是c#中异步编程的新手,并且已经阅读了几篇好文章(例如,请参阅hereherehere)。我想我已经了解它是如何运作的,但我希望有人能证实我是在正确的轨道上。

如果我理解正确,异步编程的工作原理如下:

将一个关键字async添加到一个方法中,以指示它将离开并执行自己的操作,而不依赖于程序的其余部分。它基本上就像一位厨师要求准备厨师去切蘑菇,洋葱和胡萝卜。

将异步方法分配给类型的任务。任务是正在运行的方法,或者在我们的例子中它是准备工作。返回类型是Task将返回的类型。一旦分配了任务,当前方法就会忽略它,因为它知道它正在被处理。

await命令是调用方法要求任务结果的地方。为了继续我们的榜样,厨师要求准备厨师切碎切碎的蔬菜。如果任务已完成,则给出结果,并且调用方法继续运行。如果任务尚未完成,则调用方法必须等待它完成。换句话说,如果准备厨师在厨师需要时没有完成切碎蔬菜,那么厨师必须等到他能继续制作食谱之前。 (我知道,这个比喻在这里打破了,因为真正的厨师会去做其他事情,但这只是为了简化解释。)

要使用await命令,方法必须是异步方法。在上面的示例中,调用方法是异步方法。因此,当它命中await命令时,控制权将返回其调用方法,该方法将继续运行,直到它完成或遇到它自己的await。

所以,我们现在所拥有的是方法A调用异步方法B,它调用异步方法C.方法B在await上停止,等待方法C的结果。方法A和C现在都是异步运行,而方法B正在等待结果。一旦方法C返回结果,则方法A和B将异步运行,直到方法B完成,或方法A确定它需要等待方法B的结果。注意方法B可能不需要返回结果,因此方法A可能方法B之前完成。

这听起来是对的,还是会控制从A到B,然后只有在await被击中时才返回A?因此,如果A没有自己的等待,它将在控制回到B之前完成。

我意识到我过于简单化,因为复杂程度要高得多,但我试图在细微之处之前理解这些概念。

1 个答案:

答案 0 :(得分:2)

任何时候使用await,该方法都会在此时编译为单独的方法,原始方法在此时完成(async / {{1是语法糖)。生成的方法被注册为await引用的Task的延续。如果给定方法中存在多个await,则每个await都适用相同的过程。

任何时候await用于描述方法,这意味着方法支持async可以编译成一系列延续。该方法的第一部分与调用代码一起调用,但作为await的一部分生成的部分将排队到TPL的默认调度程序(按顺序,部分完成)并根据调度程序的方式调用已配置。从await方法返回的Task将代表整个方法(因此该方法可以在方法中的任何async处取消),并且任何注册都会注册到await如果/ Task完成,将排队到TPL的默认调度程序。

在你的类比中,厨师更像是一个线程而不是一个方法。我会用术语“烹饪动作”来描述方法和延续,如果同时完成任何两个烹饪动作,那是因为厨师已将这些动作委托给一位厨师(另一个主题),除非有没有sous厨师可供选择,在这种情况下,厨师将不得不自己完成。

Async / Await

Task

Pure TPL

public void Main()
{
    var result = Calculate(1, 3).Result;

    async Task<int> Calculate(int a, int b)
    {
        var c = await Add(a, 5);
        var d = await Add(b, 3);

        return await Add(c, d);
    }

    async Task<int> Add(int a, int b)
    {
        return a + b;
    }
}