What did Await do in Chapter 1 of the asynchronous programming series ?, Chapter 4 await

Source: Internet
Author: User

What did Await do in Chapter 1 of the asynchronous programming series ?, Chapter 4 await
Preface

At the school of Asynchronization, a garden friend recommended async in C #5.0, and did not find the Chinese version. I also happen to want to improve the English version. I translated some important parts in poor English, which is purely entertaining, simple sharing, keep learning, and remember to be modest.

If you think the translation is meaningless, please step on it. If you think it is encouraging, thank you for your praise. May the garden friends who love technology leave it alone in the future. Every time you think independently, do not choose to follow the stream, or do your best, and do not do what you do, and do not live up to the meaning of each second.

For reprinting and crawlers, please refer to the original article link http://www.cnblogs.com/tdws/p/5659003.html,bokepark snail bait June 27, 2016.

Directory

Chapter 2 Introduction to asynchronous programming

Chapter 2 Why asynchronous programming

Chapter 2 manual asynchronous code writing

Chapter 4 compile the Async Method

Chapter 4 What does Await do?

Chapter 1 asynchronous mode based on tasks

Chapter 1 tools for asynchronous code

Chapter 2 which thread is running your code

Chapter 2 exceptions in asynchronous programming

Chapter 2 Concurrent Use of asynchronous programming

Chapter 4 unit test your asynchronous code

Chapter 2 asynchronous programming in ASP. NET Applications

Chapter 2 asynchronous programming in WinRT applications

Chapter 2 what does the compiler do for your Asynchronization at the underlying layer?

Chapter 1 Performance of asynchronous code

What exactly does await do?

We have two perspectives on the async features of c #5.0, especially what happened on the await Keyword:

· As a functional feature of a language, it is a defined behavior for you to learn.

· As a compile-time conversion, This Is a c # syntactic sugar. to simplify the complicated asynchronous code

This is true; they are like two sides of the same coin. In this chapter, we will focus on the first point to explore Asynchronization. InChapter 14We will discuss from another perspective, that is, more complex, but some details are provided to make debugging and performance considerations clearer.

Sleep and Wakeup

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

· To make your code asynchronous, the thread executing your code should be released. This means that, in the general and synchronous perspective, your method should be returned.

· When your await Task is completed, your method should continue from the previous position, just as it was not returned earlier.

To do this, your method must be paused when await is encountered and resume execution at a certain time in the future.

I think of this process as a small-scale scenario where a computer is sleeping (S4 sleep ). The current state of this method is stored, the cook will paste the cooking status of the food already in the oven in the form of a label), and this method completely exits (the cook is gone and may do other things ). When a computer is sleeping, its dynamic data and running data are saved to the disk and completely shut down. The following section is similar to the computer sleep. Apart from using a little memory and no other resources, an await method can be seen as the thread being executed has been released.

Taking a similar analogy: a blocking method is more like pausing a computer (S3 sleep), although it uses less resources, but it is basically running.

Ideally, we want programmers to be unaware of sleep. Even though it is complicated to sleep and wake up the middle-stage execution of a method, C # will also ensure that your code is awakened, just as nothing happens. (Translator: I have to admire Microsoft's encapsulation and processing of syntactic sugar ).

Method Status

To accurately figure out how many things C # has done for us when you use await, I want to list all the details we remember and understand about the method status.

First, the local variable values in your method will be remembered, including the following values:

· Parameters of your Method

· All the variables you define in this scope

· Other variables include the number of loops

· If your method is not static, this variable is included. In this way, the member variables of your class are available in method wake-up.

They are all stored on an object in the. NET garbage collection heap (GC heap. Therefore, when you use await, an object that consumes some resources will be allocated, but in most cases there is no need to worry about performance issues.

C # Also remembers where the method will be executed to await. This can be stored using numbers to indicate the location of the await keyword in 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 myNum = await AlexsMethodAsync(await myTask, await StuffAsync());

In order to remember the status of the remaining expression in await, additional conditions are added. For example, when we run await StuffAsync (), the results of await myTask must be remembered .. NET intermediate language (IL) stores this subclass expression on the stack. Therefore, this stack is what we need to store for the await keyword.

Most importantly, when the program executes the first await keyword, the method returnsFor how to return a method when await is encountered, we recommend that you understand the two methods split in Chapter 1.). If it is not an async void method, a Task is returned at this time, so the caller can wait for us to complete it in some way. C # must also store the method of the Task returned by an operation. In this way, when your method is completed, the Task becomes completed, and the executor can also return to the asynchronous chain of the method. The exact mechanism will beChapter 2.

Context

As part of the process to make await as transparent as possible, C # captures various contexts and restores them in the restoration method when await is encountered.

The most important thing in all things is synchronization context, which can be used to restore methods on a special type of thread. This is especially important for UI apps, that is, they can only operate the UI on the correct thread (such as winform wpf ). Synchronization context is a complex topic,Chapter 8It will be explained in detail.

Other types of context will also be captured from the currently called thread. Their control is implemented through a class with the same name, so I will list some important context types:

ExecutionContext

This is the parent context, and all other contexts are part of it. This is a system function of. NET. For example, a Task uses it to capture and disseminate context, but it does not contain any behavior.

SecurityContext

This is where we find and find the security information that is usually restricted to the current thread. If your code needs to run on a specific user, you may simulate or assume this user, or ASP. NET will help you implement the function. In this case, the simulated information will have SecurityContext.

CallContext(This is familiar. I believe all EF users know it)

This allows programmers to store data they have been available throughout the lifecycle of a logical thread. Even considering the poor performance in many cases, it can still avoid passing through the parameters of methods in the program. (TRANSLATOR: because you can get it at any time when saving it in callcontext, you do not need to pass it through the parameter ). LogicalCallContextis is a related cross-application domain.

It is worth noting that the Thread Local Storage (TLS) is similar to the CallContext target, but it does not work asynchronously, because in a time-consuming operation, the thread is released and may be used to handle other tasks. Your method may be awakened and executed on a different thread.

C # It will recover these types of context (restore, I think it refers to restoring from memory) When you restore the method (resume, here is simple "restore. Restoring the context will produce some overhead. For example, when a program uses a simulated (previous simulated identity, and so on) and extensively uses async, it will become slower. I recommend that you change the. NET context creation function unless you think this is really necessary.

Where can await be used?

Await can be used in most of the methods and methods marked with async, but in some places you cannot use await. I will explain why await is not allowed in some cases.

Catch and finally Blocks

Although await is fully allowed in try blocks, it is not allowed in catch and finally blocks. Usually in catch and finall blocks, exceptions are still unresolved in the stack and will be thrown later. If await is used before this time point, the stack will be different and the behavior of throwing an exception will become difficult to define.

Remember that the method to use block in a catch block is followed by a Boolean value to record whether the operation throws an exception. Example:

try{   page = await webClient.DownloadStringTaskAsync("http://oreilly.com");}catch (WebException){   page = await webClient.DownloadStringTaskAsync("http://oreillymirror.com");}

You can replace it as follows:

bool failed = false;try{   page = await webClient.DownloadStringTaskAsync("http://oreilly.com");}catch (WebException){   failed = true;}if (failed){   page = await webClient.DownloadStringTaskAsync("http://oreillymirror.com");}

Lock Block

Lock is a method that helps programmers prevent other threads from accessing the same object as the current thread. Because asynchronous Code usually releases the thread that starts asynchronous execution and is called back. The callback occurs after an uncertain amount of time, that is, after it is released, it is different from the start thread: even if the same thread is released, it makes no sense to lock the await.

In some cases, it is important to protect your objects from concurrent access, but it is unnecessary to use locks when no other thread accesses your objects during await. In these cases, your operations are somewhat redundant and are explicitly locked twice, as shown below:

lock (sync){    // Prepare for async operation}    int myNum = await AlexsMethodAsync();lock (sync){    // Use result of async operation}

In addition, you can use a class library to control concurrent processing, suchNAct, We willChapter 10Introduction

If you are not lucky enough, you may need to keep some lock when performing asynchronous operations. At this time, you need to think hard and be careful, because it is usually very difficult to lock the asynchronous call of resources without causing contention and deadlock. It may be the best option to try another method or refactor your program in this case.

Linq Query expression

C # has a syntax that makes it easier for us to filter, sort, and group data by writing querys. These queries can be executed on the. NET platform or converted to a database or even other data source operations.

IEnumerable<int> transformed = from x in alexsIntswhere x != 9select x + 2;

C # is not allowed to use the await keyword in the Query expression in most locations. This is because these locations are compiled into lambda expressions. Because of this, the lambda expression needs to be marked as an async keyword. However, this implicit lambda expression does not exist, even if it does, it will make people confuse.

We still have a solution. You can write Equivalent Expressions by using the extension method of the internal band of Linq. Then lambda expressions become clear and readable, And you can mark them as async to use await. (TRANSLATOR: refer to the upstream and downstream code)

IEnumerable<Task<int>> tasks = alexsInts.Where(x => x != 9).Select(async x => await DoSomthingAsync(x) + await DoSomthingElseAsync(x));IEnumerable<int> transformed = await Task.WhenAll(tasks);

To collect the results, I used Task. WhenAll, which is a tool for the Task set.Chapter 7Details.

Unsafe code

Code marked as unsafe cannot contain await. unsafe code should be very rare and the method should be dedicated and asynchronous. The unsafe code also exists when the compiler converts await. (Translator: I don't think I need to worry too much about it. I didn't write any unsafe keyword code)

Capture exceptions

Exception capture of asynchronous methods is designed by Microsoft as much as possible to synchronize code normally. However, the asynchronous complexity means there will be some nuances between them. Here I will introduce how to handle exceptions in asynchronous mode.Chapter 9Detailed instructions.

When the time-consuming operation ends, the Task type has a concept to indicate whether the operation is successful or failed. The simplest thing is that the IsFaulted attribute is used for external exposure. When an exception occurs during execution, its value is true. The await keyword detects this and throws exceptions contained in the Task.

If you are familiar with the. NET exception mechanism, you may be worried about how to properly store the exception stack trace when an exception is thrown. This may not be possible in the past. However, in. NET4.5, this restriction was modified by using a class called ExceptionDispatchInfo, that is, a class for capturing, throwing, and correct stack traces.

Asynchronous methods can also detect exceptions. Any exceptions occurred during Asynchronous Method execution will not be captured, and they will be returned to the caller as the Task returns. In this case, if the caller is in the await Task, an exception will be thrown here. (TRANSLATOR: exceptions will be passed in asynchronous mode ). In this way, exceptions are transmitted by callers, forming a virtual stack trace, just as it occurs in the synchronization code.

I take it on the virtual stack trace, because the stack is a single-thread concept, and in asynchronous code, the actual stack of the current thread and the stack of the thread that generates an exception may be very different. Exception capture is the stack trace in the user's intent, rather than the details of how C # chooses to execute these methods.

The Asynchronous Method is synchronized until it is needed.

As I mentioned earlier, await can only consume (CALL) asynchronous methods. Until the await result occurs, the statement that calls the method runs in the thread that calls them, just like the synchronous method. This is very practical, especially when a synchronous process completes all Asynchronous Method chains. (TRANSLATOR: When await is used, it is indeed executed in the synchronous order)

Remember that the asynchronous method was paused when await was first encountered. Even so, it sometimes does not need to be paused, because sometimes the await Task has been completed. A Task has been completed as follows:

· It is created by using the Task. FromResult tool. We will discuss it in detail in Chapter 7.

· Returned by the async method without async.

· It runs a real asynchronous operation, but now it has been completed (probably because the current thread has done something before await ).

· It is returned by an asunc method that encounters await, but the await has been completed before.

Due to the last possibility, some interesting things happen in a completed Task in await, probably in a deep Asynchronous Method chain. The entire chain is very similar to full synchronization. This is because in the Asynchronous Method chain, the first method called by await is always the deepest one in the Asynchronous Method chain. After other methods arrive, the deepest method will have the opportunity to return. (The others are only reached after the deepest method has had a chance to return synchronously. according to the syntax, this sentence seems to be incorrect, but I personally think the actual situation is what I said. After the first await is met, await in the Asynchronous Method chain is executed in sequence and returned one by one. Finally, the method with the deepest result is returned, that is, the first method, do some people come up with ideas here ?)

You may wonder why async is used in the first or second case. If these methods promise synchronous responses, you are correct, and the efficiency of writing Synchronous Code is higher than that of asynchronous code and there is no await process. Then, this is only the result returned by the method synchronization. For example, if a method caches its results to the memory and the cache is available, the results can be synchronously returned, but Asynchronous Network requests are required. When you know that there is a good opportunity for you to use the asynchronous method, you may also want to return the Task or Task <T> to some extent. (Asynchronous: since one of the method Chains needs to be asynchronous, it will affect the overall use of asynchronous ).

Conclusion

I still have many questions about Asynchronization. As the article gradually understands, I also hope to be faster.

Related Article

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.