Asp. NET application Synchronous call Async method crash resolution

Source: Internet
Author: User
Tags stack trace

You only know that when you call an asynchronous (Async) method in a synchronization method, if you use the. Result waits for the call results, resulting in a thread deadlock (deadlock).

Yesterday an accidental situation caused the Async method to be invoked in the synchronization method and was not used. result, resulting in the collapse of the entire ASP.net application, the experience of synchronous/asynchronous fire and fire difficult capacity.

This was the case when an asynchronous ASP.net program was released, with a synchronization method:

public static void Notify (string title, string content, int recipientid)
{
//...
}

Be modified to asynchronous method:

public static Async Task Notify (string title, string content, int recipientid)
{
Await ...
}



It was called synchronously in WebForms (. aspx) before:

<script runat= "Server" >
void Page_Load (Object sender, EventArgs e)
{
//...
Msgservice.notify (title, body, userId);
//...
}
</script>

Now call it asynchronously in the MVC Controller action:


public class Applycontroller:controller
{
[HttpPost]
Public Async task<string> Pass ()
{
//...
Await msgservice.notify (title, body, userId);
//...
}
}



This release was meant to replace WebForms with MVC, but the. aspx file of the Notify () method was not deleted from the server at the time the publication was invoked.

After the release, the ASP.net program crashes (crash) for a while, specifically:

A 503 errors were found in accessing the website;

b The corresponding application pool is displayed in the IIS Manager stop State;

c The following three errors were found in the Windows event log:

Log 1:


An unhandled exception has occurred and the process has been terminated.
Application ID:/lm/w3svc/15/root
Process id:23808
Exception:System.NullReferenceException
Message: An object reference is not set to an instance of an object.

StackTrace:
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.Threading.Tasks.AwaitTaskContinuation.RunCallback (ContextCallback callback, Object State, task& Currenttask)
---the end of the stack trace in the previous location where the exception was thrown---
In System.threading.tasks.awaittaskcontinuation.<throwasyncifnecessary>b__1 (Object s)
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 ()



Log 2:

Application: W3wp.exe
Framework version: v4.0.30319
Description: The process terminates due to an unhandled exception.
Exception information: System.NullReferenceException
Stack:
In System.threading.tasks.awaittaskcontinuation.<throwasyncifnecessary>b__1 (System.Object)
In System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
In System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
In System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem ()
In System.Threading.ThreadPoolWorkQueue.Dispatch ()



Log 3:

Faulting application Name:w3wp.exe, version:7.5.7601.17514, Time STAMP:0X4CE7AFA2
Faulting module Name:KERNELBASE.dll, version:6.1.7601.18798, Time stamp:0x5507b87a
Exception code:0xe0434352
Fault Offset:0x000000000001aaad
Faulting process id:0x5d00
Faulting application start time:0x01d0b86f3af9058e
Faulting application Path:c:\windows\system32\inetsrv\w3wp.exe
Faulting module Path:c:\windows\system32\kernelbase.dll
id:7bec0e6c-2462-11e5-b24e-c43d8baaa802



From the log information, the problem is definitely asynchronous, so check all the code that makes the asynchronous call, but not the problem (except to check for an. aspx file that is not being used, not deleted).

Only later did I think of the. aspx file that was not deleted, but it has been replaced by MVC, not in use. If it's caused, there's only one possibility ... This file is still being accessed by some requests. After careful investigation found that the original is to refer to JS place without hash parameters, resulting in some client browsers due to the caching reasons are still using the old version of JS, the old version of JS will also send an AJAX request to this. aspx file.

It was an oversight that caused the asynchronous method to be invoked directly in the synchronization method, but it never occurred to me that it was so powerful that it caused the entire application to crash, so curiosity was stimulated.

After reading some information on the Internet, we have some understanding of this problem.

In asp.net (asp.net is inherently multi-threaded, thread-pool based, no UI thread concept), if you call a async method, if you have await accompanying, the current line Cheng Lima is released back to the thread pool, the threads ' contextual information (such as Reqeust Context) is saved, if there is no await accompanying (and no other wait code), the code will continue to execute until the Async method is invoked, until completion, and the current thread is freed back to the thread pool, and the thread's contextual information is not saved. When the asynchronous task in async is complete (note: An asynchronous task is not done in another thread, it is done in a state machine, and a thread is removed from the thread pool to continue execution, which reads the context information of the original thread that invoked it (by default). If Configureawait (false), there is no such step, if the original call without using await, the thread's contextual information is not saved, then the NullReferenceException is raised. The unhandled null reference exception that occurs at this level causes the entire application to crash, or more precisely the process where the application is located. Because such an anomaly is too dangerous, in order not to let a mouse broke a pot of soup, can only be sacrificed.

So, if you don't want to be sacrificed, either honestly await, or tell the Async method, do not read the context information (Configureawait (false) of the original thread, or whether it is valid without actual validation), or the thread that calls the Async method does not have context information to save , such as calling the Async method in Task.run (or Task.Factory.StartNew), that is, invoking the Async method with a new thread.




Async and await in C #

Async/task/await three combinations are the. NET Framework 4.5 brought to. NET Developer's gift, use it reasonably, can increase the throughput ability of the application.

But if used incorrectly, it can bring unexpected problems-such as waiting after await.

First look at a asp.net MVC sample code:

public class Blogcontroller:controller
{
Public async task<actionresult> Awaitdemo ()
{
var responsehtml = getresponsehtml ("http://www.cnblogs.com/");
Return Content (responsehtml);
}

private string getresponsehtml (string url)
{
return Getresponsecontentasync (URL). result;
}

Private Async task<string> getresponsecontentasync (string url)
{
var httpclient = new System.Net.Http.HttpClient ();
var response = await httpclient.getasync (URL);
if (response. StatusCode = = System.Net.HttpStatusCode.OK)
{
return await response. Content.readasstringasync ();
}
Else
{
return "error";
}
}
}


Code Description:

In the above code, although async Task<actionresult&gt is added before the action method, it is actually performed synchronously, as is the case with the direct use of actionresult, because await is not used in the method body.
Getresponsehtml is a synchronous method, Getresponsecontentasync is an asynchronous method, and an asynchronous getresponsecontentasync is invoked in getresponsehtml. (If a third party assembly is invoked, we do not know that an asynchronous call is made in getresponsehtml, so the design of this method is problematic)

What is the result of this code execution?

--The result is no results, has been executing ...

(Note: This problem does not occur if you invoke the same getresponsehtml in a console application.)

What if it solves this problem:

Workaround One: Open a task in the MVC action to await

Public async task<actionresult> Awaitdemo ()
{
var responsehtml = await Task.Factory.StartNew (() =>
Getresponsehtml ("http://www.cnblogs.com/"));
Return Content (responsehtml);
}


Workaround two: Turn getresponsehtml into an asynchronous method

Public async task<actionresult> Awaitdemo ()
{
var responsehtml = await getresponsehtml ("http://www.cnblogs.com/");
Return Content (responsehtml);
}

Private Async task<string> getresponsehtml (string url)
{
Return await Getresponsecontentasync (URL);
}


Obviously, the 2nd solution is better.

So, when we design a method, if we call the Async method, we must design the method itself as async. Otherwise, when others call, they always wait.


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.