简体   繁体   中英

Is this how Asynchronous Flow Works

I am new to asynchronous programming in c#, and have read several good articles on it (see here , here , and here for examples). I think I have an understanding of how it works, but am hoping that someone can confirm that I am on the right track.

If I understand this correctly, Asynchronous Programming works like this:

Add the keyword async to a method to indicate that it will wander off and do its own thing, independent of what the rest of the program is doing. It is basically like a chef asking a prep-cook to go off and cut mushrooms, onions and carrots.

The async method is assigned to a Task of type . The Task is the method that is running, or in our case it is the prep cook. The return type is the type that the Task will return. Once the task is assigned, the current method ignores it, knowing that it is being worked on.

The await command is where the calling method is asking for the Task results. To continue our example, the chef asks the prep cook for the chopped veggies. If the Task has been completed, the result is given, and the calling method continues to run. If the task is not yet complete, the calling method must wait for it to complete. In other words, if the prep cook has not finished chopping the vegetables by the time the chef needs them, then the chef must wait before he can continue making the recipe. (I know, the metaphor breaks down here because a real chef would go off and do something else, but this is only to simplify the explanation.)

To use the await command, a method must be an async method. In the example above, the calling method is an async method. Thus, when it hits the await command, control goes back to its calling method, which will continue to run until it completes or comes across an await of its own.

So, what we have now is that method A calls async method B, which calls async method C. Method B is stopped on an await, waiting for results from method C. Method A and C are both running asynchronously now, while method B is waiting for results. Once method C returns the results, then method A and B will run asynchronously until either method B completes, or method A decides that it needs to await results from method B. Note that method B may not need to return results, so method A may complete before method B does.

Does this sound right, or would control go from A to B, and then only return to A when the await is hit? Thus if A does not have an await of its own, it would finish up before control went back to B.

I realize I'm oversimplifying this where there is a lot more complexity, but I am trying to understand the concepts before the subtleties.

Any time await is used, the method is at that point compiled in to a seperate method and the original method completes at that point ( async / await is syntactic sugar). The generated method is registered as a continuation of the Task to which the await refers. If there exists more than a single await within a given method, then the same procedure applies for each await .

Any time async is used to describe a method, it means that method supports await and can be compiled in to a series of continuations. The first portion of the method is invoked inline with the calling code, but the portions generated as part of an await will be queued to the TPL's default scheduler (in order, as portions complete) and called according to how that scheduler is configured. A Task returned from an async method will represent the method as a whole (thus the method can be canceled at any await within the method), and any continuation registered to that Task will be queued to the TPL's default scheduler if/when that Task completes.

In your analogy, the chef is more akin to a thread than a method. I'd use the term "cooking action" to describe the methods and continuations, and if any two cooking actions are done at the same time, it's because the chef has delegated those actions to a sous chef (another thread), unless there are no sous chefs available, in which case the chef will just have to do it himself later.

Async / Await

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;
    }
}

Pure TPL

public void Main()
{
    const int a = 1;
    const int b = 3;

    var t1 = Task.Run(() => new
        {
            c = a + 5
        }
    );

    var t2 = t1.ContinueWith(t =>
        new
        {
            c = t.Result.c,
            d = b + 3
        }
    );

    var t3 = t2.ContinueWith(t =>
        t.Result.c + t.Result.d
    );

    var result = t3.Result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM