Performing an Asynchronous Operation Invoked by an ASP.NET Web Page Request

I have an asynchronous operation that for various reasons needs to be launched using an HTTP call to an ASP.NET web page. When my page is requested, it should start this operation and immediately return confirmation to the client.

This method is also displayed through the WCF web service, and it works great.

On my first attempt, an exception was thrown, telling me:

  Asynchronous operations are not allowed in this context.
 Page starting an asynchronous operation has to have the Async
 attribute set to true and an asynchronous operation can only be
 started on a page prior to PreRenderComplete event. 

Therefore, of course, I added the Async="true" parameter to the @Page directive. Now I do not receive an error message, but the page is blocked until the asynchronous operation is completed.

How can I get a true page with fire and oblivion?

Edit: Some code for more information. This is a little more complicated than that, but I tried to get a general idea there.

 public partial class SendMessagePage : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { string message = Request.QueryString["Message"]; string clientId = Request.QueryString["ClientId"]; AsyncMessageSender sender = new AsyncMessageSender(clientId, message); sender.Start(); Response.Write("Success"); } } 

AsyncMessageSender Class:

 public class AsyncMessageSender { private BackgroundWorker backgroundWorker; private string client; private string msg; public AsyncMessageSender(string clientId, string message) { this.client = clientId; this.msg = message; // setup background thread to listen backgroundThread = new BackgroundWorker(); backgroundThread.WorkerSupportsCancellation = true; backgroundThread.DoWork += new DoWorkEventHandler(backgroundThread_DoWork); } public void Start() { backgroundThread.RunWorkerAsync(); } ... // after that it pretty predictable } 
+46
c # asynchronous
Mar 23 '09 at 4:28
source share
5 answers

If you do not want to return anything to the user, you can simply start either a separate thread or a quick and dirty approach, use a delegate and call it asynchronously. If you do not need to notify the user of the completion of the async task, you can ignore the callback. Try putting a breakpoint at the end of the SomeVeryLongAction () method, and you will see that it ends after the page is already submitted:

 private delegate void DoStuff(); //delegate for the action protected void Page_Load(object sender, EventArgs e) { } protected void Button1_Click(object sender, EventArgs e) { //create the delegate DoStuff myAction = new DoStuff(SomeVeryLongAction); //invoke it asynchrnously, control passes to next statement myAction.BeginInvoke(null, null); Button1.Text = DateTime.Now.ToString(); } private void SomeVeryLongAction() { for (int i = 0; i < 100; i++) { //simulation of some VERY long job System.Threading.Thread.Sleep(100); } } 
+28
Mar 23 '09 at 5:03
source share

OK, here is the problem: the Async attribute is designed for the case when your page will cause some long-term task that also blocks the flow, and then your page needs to exit this task in order to return the information to the User. For example, if your page is needed to call a web service, wait for it to respond, and then use the data from the response to display your page.

The reason for using the Async attribute is to prevent thread blocking. This is important because ASP.NET applications use a thread pool to serve requests, and only a relatively small number of threads are available. And if each call associates a thread while waiting for a web service call, then soon you will encounter a sufficient number of concurrent users who will have to wait until the calls to these web services are completed. The Async attribute allows a thread to return to the thread pool and serve other concurrent visitors on your website, rather than making it sit and do nothing while waiting for the web service call to return.

The result is for you: the Async attribute is designed for the case when you cannot display the page until the asynchronous task is completed and why it does not display the page immediately.

You need to start your own thread and make it a daemon thread. I don’t remember the exact syntax for this, but you can easily find it in a document by searching for a BCL document for daemon. This means that the thread will close your application while it is alive, which is important because ASP.NET and IIS reserve the right to β€œre-process your process” when they consider it necessary, and if this happens while your thread is running, Your task will be stopped. Creating a thread daemon will prevent this (with the exception of some possible cases of rare edges ... you'll learn more when you find documentation on this).

This daemon flow is where you begin to perform these tasks. And after you told the daemon thread to complete the task, you can immediately display your page ... so that the page will render immediately.

However, even better than the daemon thread in your ASP.NET process, it will implement a Windows service to accomplish this task. Ask the ASP.NET application to submit the task that will run in the Service. There is no need for a daemon thread, and you do not have to worry about your ASP.NET process being processed. How do you inform the Service about this task? Perhaps through WCF, or, perhaps, by inserting a record into the database table that the Service polls. Or a few other ways.

EDIT: Here is another idea that I used earlier for the same purpose. Write information about your task to the MSMQ queue. Ask another process (perhaps even on a different machine) to pull it out of this queue and perform a time-consuming task. The task of inserting into a queue is optimized to return as quickly as possible, so your stream will not be blocked, and the data that you put in the queue is sent by wiring or something like that. This is one of the fastest ways to pay attention to the fact that you need to complete a task without waiting for the task to complete.

+25
Mar 23 '09 at 5:22
source share

If you use webforms, set Ansync = "true" on the .aspx page where you make the request.
<%@ Page Language="C#" Async="true" ... %>

+21
Aug 27 '13 at 7:21
source share

You can easily get around this limitation and not even set Async to true.

 public void Start() { new Task(() => { backgroundThread.RunWorkerAsync(); }).Start(); } 
+2
Jun 28 '13 at 9:30
source share

If you get this error when asynchronously invoking a web service, be sure to add the Async = 'true' attribute as indicated in the exception message?

at the top of the page <Page Language = 'VB' Async = 'true' AutoEventWireup = 'false' CodeFile = 'mynewpage.aspx.vb' Inherits = 'mynewpage'%>

+1
Dec 28 '12 at 23:11
source share



All Articles