ASP. NET: Use async/await, asp. netasyncawait

Source: Internet
Author: User

ASP. NET: Use async/await, asp. netasyncawait

C #5.0 introduces the async/await keyword to simplify the asynchronous programming model. Throwing away the syntactic sugar is Net4.0's Task + state machine. In fact, it is quite simple to use tasks in asynchronous programming. However, since the new syntax sugar is introduced, it is inevitable to try it. However, it is not as simple as you think. The following are some summary of the actual use of ASP. NET applications, including exception capture, deadlocks, and application crashes. during actual use, you may lose the pitfalls if you do not pay attention to them.

Exception capture

The async method has three return types: void, Task, and Task.

Async void

The Methods declared in this method cannot catch exceptions, so try and catch of the following code are useless.

Private static async void ThrowExceptionAsync () {await Task. delay (1000); throw new Exception ("throwing an Exception to play");} public static async void CatchAsyncVoidException () {try {ThrowExceptionAsync ();} catch (Exception ex) {throw ex ;}}

Async Task or async Task

The exception information of the Methods declared in the two methods will contain the Task attribute, but the await must be used in the try.

Private static async Task ThrowExceptionAsync () {await Task. delay (1000); throw new Exception ("throwing an Exception to play");} public static async Task CatchAsyncTaskException () {try {await ThrowExceptionAsync ();} catch (Exception ex) {throw ex ;}} TaskScheduler. unobservedTaskException

For uncaptured Task exceptions, you can set Global taskschedexception. UnobservedTaskException to record error logs. Add the following code in Global. asax:

Void Application_Start (object sender, EventArgs e) {// code TaskScheduler that runs when the application starts. unobservedTaskException + = TaskScheduler_UnobservedTaskExceptionException;} void TaskScheduler_UnobservedTaskExceptionException (object sender, UnobservedTaskExceptionEventArgs e) {if (e. exception! = Null) {// do something }}

Synchronization Context

Asynchronous programming must be about the use of threads. threads have a synchronization context concept. I personally think that the thread synchronization context is the most worrying problem encountered by async/await. In the development of existing projects, we may want to try to use async/await, but the old code is synchronous. If we call a method declared as async, the deadlock and application crash may occur accidentally.

Note: Console programs and. Net Core programs will not encounter this problem, and they do not need to synchronize context.

Deadlock

private static async Task XXXAsync(){ await Task.Delay(1000);  // some code}public static void Test(){ var task = XXXAsync(); task.Wait();}

The above code perfectly implements the deadlock. By default, when Wait () is not completed, the context of the current thread is captured, and the execution of the context restoration method is used when the Task is completed. When the await execution in the async method is complete, it will try to obtain the remaining part of the context execution method of the caller thread, but the context already contains a thread, which is waiting for the async method to complete. Then they waited for each other, and then they died.

The solution to the deadlock problem is to add ConfigureAwait (false)

// Await Task. Delay (1000); await Task. Delay (1000). ConfigureAwait (false); // solves the deadlock

When await waits for completion, it will try to execute the remaining part of the async method in the thread pool, so there is no deadlock.

Application crash

The test environment always finds that the IIS application pool is always crashed. Why? At that time, we were very reluctant to solve this problem. The Code did not seem to have any obvious problems. It should be a problem of the environment itself to try to cheat ourselves, but in fact it was actually a poison in the code. Through Reading and testing various materials, we can basically conclude that it is a problem caused by Synchronous Code calling asynchronous code and synchronization context.

If you call an async method. If await is used, the current thread is immediately released back to the thread pool, and the context information of the thread is saved. If the await (async void method is not used, await cannot be used), after the async method is called, the Code continues to be executed. After the execution is complete, the current thread is released back to the thread pool, the context information of the thread is not saved. After an asynchronous task in async is executed, it obtains a thread from the thread pool to continue executing the remaining code, at the same time, it will obtain the context information of the thread where the caller was originally located (if the caller's thread was not released back to the thread pool, the context information can be obtained ). The problem arises. If the caller did not use await and the thread in which it is located is released back to the thread pool, the context information cannot be obtained because it is not kept, at this time, an exception will be thrown, and the object reference is not set to the instance of the object. After testing, this exception information does not necessarily appear every time. The reason is related to the release of the thread, if the context information of the thread where the caller is located exists, no exception is thrown. The error message is as follows. This exception will eventually stop the application assembly.

In System. web. threadContext. associateWithCurrentThread (Boolean setImpersonationContext) in System. web. httpApplication. onThreadEnterPrivate (Boolean setImpersonationContext) in System. web. legacyAspNetSynchronizationContext. callCallbackPossiblyUnderLock (SendOrPostCallback callback, Object state) in System. web. legacyAspNetSynchronizationContext. callCallback (SendOrPostCallback callback, Object state) in System. web. legacyAspNetSynchronizationContext. post (SendOrPostCallback callback, Object state) in System. threading. tasks. synchronizationContextAwaitTaskContinuation. postAction (Object state) in System. threading. tasks. awaitTaskContinuation. runCallback (ContextCallback callback, Object state, Task & currentTask) --- The end of stack trace in the previous position where an exception is thrown --- in System. threading. tasks. awaitTaskContinuation. <> c. <ThrowAsyncIfNecessary> B _ 18_0 (Object s) in System. threading. queueUserWorkItemCallback. waitCallback_Context (Object state) in System. threading. executionContext. runInternal (ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) in System. threading. executionContext. run (ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) in System. threading. queueUserWorkItemCallback. system. threading. IThreadPoolWorkItem. executeWorkItem () in System. threading. threadPoolWorkQueue. dispatch () in System. threading. _ ThreadPoolWaitCallback. performWaitCallback ()

How can we solve the above exceptions? It is still ConfigureAwait (false). When ConfigureAwait (false) is added to the Task, this setting means that when the asynchronous Task in async is completed, it does not read the context information of the original thread that was called at the time, the remainder of async method execution in the thread pool.

public static Task XXXAsync(){ await Task.Run(() => { // some code }).ConfigureAwait(false);}

Summary

The above is the introduction of ASP. NET. I would like to use async/await and hope to help you. If you have any questions, please leave a message and I will reply to you in a timely manner. Thank you very much for your support for the help House website!

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.