Asynchronous Programming Series No. 05 what did await?

Source: Internet
Author: User
Tags stack trace

Write in front

Learning Async, a friend recommended the "async in c#5.0", did not find the Chinese version, coincidentally also want to improve the English, with my poor English translation of some important parts, purely entertainment, simple sharing, keep learning, remember humility.

If you think this is a bad thing to translate, just step on it. If you feel worthy of encouragement, thank you for leaving your praise, may love the technology of the park friends in the future every time should be a drastic breakthrough, do not choose to quit. In each time should think independently, do not choose to drift, should go all out, do not choose to do their best, live up to every second the meaning of existence.

Reprint and crawler Please indicate the original link http://www.cnblogs.com/tdws/p/5659003.html, blog park snail June 27, 2016.

Directory

The No. 01 chapter introduces the asynchronous programming

The No. 02 Chapter Why asynchronous Programming is used

No. 03 Manual Asynchronous code Writing

No. 04. Writing Async Methods

The No. 05 Chapter What is the await?

No. 06. Task-based Asynchronous Pattern

No. 07. Some tools for asynchronous code

No. 08 Chapter which thread is running your code

No. 09. Exceptions in Asynchronous programming

The 10th chapter uses asynchronous programming in parallel

11th Unit Test Your async code

The 12th Chapter ASP. NET applications for asynchronous programming

13th. Asynchronous Programming in WINRT applications

14th. What does the compiler do for your async at the bottom?

15th performance of asynchronous code

What exactly did await?

We have two angles to look at the async features of c#5.0, especially what happens on the await keyword:

• As a functional feature of a language, he is a well-defined behavior for you to learn

• As a conversion at compile time, this is a C # syntax for sugar, in order to briefly pre-complicate the asynchronous code

It's all true; they're like two sides of the same coin. In this chapter, we will focus on the 1th to explore Asynchrony. In Chapter 14 We will explore from another perspective, which is more complex, but provides some details to make debug and performance considerations clearer.

Hibernate and wake up a method

When your program execution encounters the await keyword, we want to happen two things:

• To make your code asynchronous, the thread that is currently executing your code should be freed. This means that, in a normal, synchronized perspective, your method should return.

• When the task you await is completed, your method should continue from its previous position, as if it had not been returned earlier.

In order to do this, your method must be paused when it encounters an await, and then resume execution at some point in the future.

I think of this process as a small-scale case of sleeping on a computer (S4 sleep). The current state of this method is stored (translator: The state is stored, as in our second chapter of the kitchen, the chef will put the cooking state of the food that has been placed in the oven in the form of a label), and this method exits completely (the chef is gone and may be doing something else). When a computer sleeps, the computer's dynamic data and running data are saved to disk and become completely shut down. The following paragraph and the computer sleep about a reason, an await method in addition to a bit of memory, do not use other resources, it can be considered that the executing thread has been released.

Take a closer look at the analogy of the previous paragraph: A blocking method is more like pausing a computer (S3 sleep), although it uses less resources, but fundamentally it is running.

Ideally, we want the programmer to be unaware of the hibernation here. Although it is complex to actually hibernate and wake up a method's mid-term execution, C # will also ensure that your code is awakened as if nothing had happened. (Translator: Have to marvel at Microsoft's encapsulation and processing of syntactic sugars).

Method of Status

To get a good idea of exactly how much C # has done for us when you use await, I want to list all the details that we remember and understand about the state of the method.

First, the values of the local variables in your method are remembered, including the following values:

• Parameters of your method

• All variables that you define within the scope

• Other variables include the number of loops

• If your method is non-static, then include the This variable. In this way, the member variables of your class are available when the method wakes up.

They are all present on an object of the. NET recycle heap. So when you use await, an object that consumes some resources will be allocated, but in most cases you don't have to worry about performance issues.

C # also remembers where the method will be executed to await. This can be stored using numbers to indicate where the await keyword is at the current method.

There are no special restrictions on how to use the await keyword, for example, they can be used on a long expression and may contain more than one await:

int await Alexsmethodasync (awaitawait stuffasync ());

In order to remember the state of the remaining expressions when waiting for something, additional conditions are added. For example, when we run await Stuffasync (), the result of the await mytask needs to be remembered. NET intermediate language (IL) stores this seed class expression on the stack, so this stack is what we need to store the await keyword.

Most importantly, the method returns when the program executes to the first await keyword. If it is not an async void method, a task is returned at this moment, so the caller can wait for us to finish in some way. C # must also store a way to manipulate the returned task so that when your method finishes, the task becomes completed, and the performer can return to the async chain of the method. The exact mechanism will be introduced in the 14th Chapter .

Context

As a part of making the await process as transparent as possible, C # captures various contexts when encountering an await, and then restores the method so that it recovers.

The most important thing in all things is the synchronization context (synchronization contexts), which can be used for recovery methods on a particular type of thread. This is especially important for UI apps, which are those that can only manipulate the UI on the right thread (that is, WinForm WPF). The synchronization context is a complex topic, and the eighth chapter will explain it in detail.

Other types of contexts are also captured from the thread that is currently being called. Their control is implemented by a class of the same name, so I'll list some important context types:

ExecutionContext

This is the parent context, and all other contexts are part of it. This is. NET's system functionality, such as a task, uses its capture and propagation context, but it does not itself contain any behavior.

SecurityContext

This is where we find and find security information that is usually restricted to the current thread. If your code needs to run on a specific user, you might, impersonate or play the user, or ASP. NET will help you play. In this case, the impersonation information will exist SecurityContext.

CallContext(This is a familiar thing, I believe it's known by EF)

This allows programmers to store data that they have been available for the lifetime of the logical thread. Even considering the bad performance in many cases, it can still avoid the parameters of the method in the program to pass. (Translator: Because you are in the CallContext, you can get it anytime, you don't have to pass the parameters to pass it). Logicalcallcontextis is a related application domain that can be cross-used.

Note that thread-local storage (TLS), which is similar to CallContext's target, is not working asynchronously, because in a time-consuming operation, the thread is freed and may be used to handle other things. Your method may be awakened and executed on a different thread.

C # will recover these types of contexts (restore, I think this refers to recovering from memory) in your method recovery (resume, here is pure "recovery"). The recovery context will incur some overhead, for example, when a program uses impersonation (a pre-impersonated identity, and so on) and uses async a lot more slowly. I suggest that it will change. NET creates the functionality of the context unless you think it is really necessary.

Where can I use the await?

Await can be used in any of the methods and methods that mark Async, but in some places you cannot use await. I will explain why the await is not allowed in some cases.

catch and finally blocks

Although it is entirely permissible to use await in a try block, he is not allowed to use it in catch and finally blocks. Typically in catch and finall blocks, exceptions remain unresolved in the stack, and are then thrown. If the await is used before this time, the stack will be different, and the behavior of throwing the exception will become difficult to define.

Remember that the alternative to using block in a catch block is after it, by returning a Boolean value to record whether the operation throws an exception. Examples are as follows:

Try {   await Webclient.downloadstringtaskasync ("http://oreilly.com" );} Catch (webexception) {   await Webclient.downloadstringtaskasync ("http/ oreillymirror.com");}

You can replace it in the following ways:

BOOLFailed =false;Try{page=awaitWebclient.downloadstringtaskasync ("http://oreilly.com");}Catch(WebException) {failed=true;}if(failed) {page=awaitWebclient.downloadstringtaskasync ("http://oreillymirror.com");}

Lock Block

Lock is a way to help programmers prevent other threads and the current thread from accessing the same object. Because asynchronous code usually frees the thread that started executing the asynchronous and is called back and the callback occurs after an indeterminate amount of time, that is, after being freed and starting the thread is different (translator: even if the same thread, it is also released after the), so the lock on the await does not make any sense.

In some cases, it is important to protect your objects from concurrent access, but it is not necessary to use locks when no other thread is accessing your objects during an await. In these cases, your operation is somewhat redundant and has been explicitly locked two times, as follows:

Lock (sync) {    //  Prepare for async operation}    intawait  Alexsmethodasync (); Lock (sync) {    // use result of async operation}

In addition, you can use a class library to handle concurrency control, such as nact, which we will introduce in the tenth chapter

If you are not lucky, you may need to keep some kind of lock while performing an asynchronous operation. At this point, you need to put your brains and care into it, because it is often difficult to lock out asynchronous calling resources without creating contention and deadlocks. Maybe it's best to think of other options or refactor your program in this situation.

Linq query Expressions

C # has a syntax that helps us make it easier to write querys to filter, sort, group, and more. These query can be executed on the. NET platform or into database operations or even other data source operations.

ienumerable<int from in alexsintswhere9Select 2;

C # is in most locations where the await keyword is not allowed in a query expression. Because these locations are compiled into lambda expressions, the lambda expression needs to be marked as the Async keyword. It's just that the implicit lambda expression doesn't exist, even if it really does make people confuse.

We still have a way that you can write an equivalent expression by using the LINQ inner Band extension method. Then the lambda expression becomes clear and readable, and then you can mark them as async, thus using await. (Translator: Please read it against the upper and lower code)

ienumerable<task<int>> tasks =9). Select (asyncawaitawait  dosomthingelseasync (x)); IEnumerable<int  await task.whenall (tasks);

To collect the results, I used Task.whenall, which is the tool for the task collection, and I'll cover the details in chapter seventh .

Unsafe Code

Code that is marked unsafe cannot contain await, non-secure code should be very rare and should keep the method alone and do not need to be asynchronous. Anyway, the compiler will jump out of the unsafe code when it transitions to await. (Translator: I think it's not too much to care about here, anyway, I didn't write the code of the unsafe keyword)

Catching exceptions

The exception captures for async methods are designed by Microsoft as much as we normally do with synchronous code. However, the complexity of asynchrony means that there are subtle differences between them. Here I'll show you how async can handle exceptions in a nutshell, and I'll explain the caveats in the Nineth Chapter .

When the time-consuming operation finishes, the task type has a concept to indicate success or failure. The simplest is to expose it by the Isfaulted property, and its value is true when an exception occurs during execution. The await keyword will perceive this and throw the exception contained in the task.

If you are familiar with. NET exception mechanism, using a stack trace that might be concerned about the exception, how to save correctly when throwing an exception. This may not have been possible in the past. However in. In NET4.5, this restriction has been modified by a class called Exceptiondispatchinfo, that is, a cooperative exception catching, throwing and the correct stack trace.

Asynchronous methods can also detect exceptions. Any exceptions that occur during the execution of an asynchronous method are not captured, and they are returned to the caller as the task returns. When this happens, if the caller is waiting for the task, the exception will be thrown here. (translator: Previously mentioned that exceptions are passed in async). In this way, the exception propagates through the caller, forming a virtual stack trace exactly as it would happen in the synchronous code.

I take it on a virtual stack trace because the stack is a single-threaded concept, and in async code, the actual stack of the current thread and the stack of the thread that produces the exception may be very different. Exceptions capture stack traces in user intent, not how C # chooses to perform these methods in detail.

Until it is required, the async methods are synchronous.

As I said before, using await can only consume (invoke) Async methods. Until the await result occurs, the statement that invokes the method runs in the thread that calls them, just like a synchronous method. This is very practical, especially when all asynchronous method chains are completed in a synchronous process. (Translator: When using await, it is true that it is performed in the Order of synchronization)

Remember that the Async method paused before the first time you encountered an await. Even so, it sometimes does not need to be paused, because sometimes the await task is completed. The situation where a task has been completed is as follows:

• He was created through the Task.fromresult tool method. We will discuss it in detail in the seventh chapter.

• Returned by an Async method that did not encounter async.

• It runs a real asynchronous operation, but is now complete (probably because the current thread has done something before it encounters an await).

• It is returned by a Asunc method that encounters an await, but this is done before the await.

Because of the last possibility, something interesting happens when you await an already completed task, most likely in a deep asynchronous method chain. The whole chain is much like a fully synchronized. This is because in the Async method chain, the first await called method is always the deepest of the async chain. When other methods arrive, the deepest method has the opportunity to return. (The others is reached after the deepest method have had a chance to return synchronously. Translator: According to grammar, my sentence seems to be translated incorrectly, but I Personally, I think the reality is what I'm talking about. After encountering the first await, the await in the back async method chain executes sequentially, returns one by one, and finally returns the result to the deepest method, that is, the first method, is there an expert to present the opinion here? )

You may wonder why async is used in the first or second case. If these methods promise to be returned synchronously, you are correct, and the code for writing synchronization is more efficient than asynchronous and there is no await process. Then, this is just the way the method returns synchronously. For example, a method caches its results into memory, and when the cache is available, the results can be returned synchronously, but when it requires an asynchronous network request. When you know there is a good chance for you to use asynchronous methods, you may also want to somehow return to a task or task>t<. (Async: Since there is one in the method chain to be asynchronous, it affects the overall use of async).

Written in the last

About Async I have a lot of doubts, but also with the article gradually understand, I also hope to be faster AH.

Asynchronous Programming Series No. 05 what did await?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.