The Disturbed Buddha

Simple Observations of a Self-proclaimed Novice

Handling Multiple Asynchronous Postbacks

Sometimes multiple asynchronous postbacks get triggered. Now, I’m not talking about situations where we want to disable a submit button, so that the user doesn’t click it fifty times waiting for something to happen. Instead, I’m referring to situations where we do want each postback to happen in the order it was fired.

However, when a page makes multiple asynchronous postbacks at the same time, the default action is that the PageRequestManager gives the most recent postback precedence. This cancels any prior asynchronous postback requests that have not yet been processed. (Get further explanation.)

So, let’s create a way to “queue up” our asynchronous postback requests and fire them off in order, one by one. First, let’s create an aspx page with three buttons inside of an UpdatePanel:

<asp:ScriptManager ID="ScriptManager1" runat="server" /> 
<asp:UpdatePanel ID="UpdatePanel1" runat="server"> 
    <ContentTemplate> 
        <asp:Button ID="Button1" runat="server" Text="Button" /> 
        <asp:Button ID="Button2" runat="server" Text="Button" /> 
        <asp:Button ID="Button3" runat="server" Text="Button" /> 
    </ContentTemplate> 
</asp:UpdatePanel>

There is no need to wire up any click events in the code-behind for our sample. While you could, all that we are concerned about is that they each cause a postback.

Next, let’s add some deliberate latency into the code so that our postback requests can pile up. Every postback to the server will now take 3 ½ seconds, so that is the fastest each request can be processed.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
  System.Threading.Thread.Sleep(3500) 
End Sub

Now, let’s look at the JavaScript code that will manage the backed-up postback requests for us. Add this script block after the ScriptManager on the page but before the closing </html> tag.

<script type="text/javascript"> 
    var prm = Sys.WebForms.PageRequestManager.getInstance(); 
    prm.add_initializeRequest(InitializeRequestHandler); 
    prm.add_endRequest(EndRequestHandler);        

    var pbQueue = new Array(); 
    var argsQueue = new Array();       

    function InitializeRequestHandler(sender, args) { 
        if (prm.get_isInAsyncPostBack()) { 
            args.set_cancel(true); 
            pbQueue.push(args.get_postBackElement().id); 
            argsQueue.push(document.forms[0].__EVENTARGUMENT.value); 
        } 
    }       

    function EndRequestHandler(sender, args) { 
        if (pbQueue.length > 0) { 
            __doPostBack(pbQueue.shift(), argsQueue.shift()); 
        } 
    } 
</script>

The Code in Detail

First, we use the PageRequestManager to set up handlers for the beginning and end of each asynchronous request:

var prm = Sys.WebForms.PageRequestManager.getInstance(); 
prm.add_initializeRequest(InitializeRequestHandler); 
prm.add_endRequest(EndRequestHandler);

Queuing up the Postbacks…

Then we create an array to store the originator of each asynchronous postback that cannot be processed immediately, as well as an array to store any event arguments associated with the postback:

var pbQueue = new Array(); 
var argsQueue = new Array();

Then, at the beginning of each asynchronous postback, we check to see if the page is already in an asynchronous postback:

function InitializeRequestHandler(sender, args) { 
    if (prm.get_isInAsyncPostBack()) {...}

If it is, we cancel the new postback request, and instead, add the event target and arguments to our arrays:

args.set_cancel(true); 
pbQueue.push(args.get_postBackElement().id); 
argsQue.push(document.forms[0].__EVENTARGUMENT.value);

…and Executing Them

After each asynchronous postback completes, we check to see if there are any more queued up, and if so, we do a __doPostBack(). pbQueue.shift() pulls the first item out of the array and removes it.

function EndRequestHandler(sender, args) { 
    if (pbQueue.length > 0) { 
        __doPostBack(pbQueue.shift(), argsQueue.shift()); 
    } 
}

And that’s it. Run the page, and randomly click some buttons! If you watch the browser’s status bar, you’ll see the asynchronous postbacks piling up. Then, every 3 ½ seconds, you’ll see one of them being processed! (Remember, the 3 ½ seconds is just an arbitrary time that we added into this demonstration, and it has nothing to do with how the code really works.)

Note: If for some reason, you wanted to execute the asynchronous postbacks in reverse chronological order (i.e., the most recent requests get processed first), just replace the array.shift() command in the EndRequestHandler() with array.pop().

About these ads

December 12, 2007 - Posted by | Ajax, ASP.NET, Javascript, Web Development

10 Comments »

  1. Good post and good site…nice and simple, although I am having a hard time getting this example of yours to work.

    Your example will capture, store, and correctly re-call _dopostback, but I feel like something is missing here because while the queued requests are sent and received, only the first request will actually be updated by the browser. For example, say I had a gridview inside of an updatepanel control with two sortable columns and I clicked on the first column header (to initiate a postback that will do the sort) and then the second (queueing the 2nd request). The first request will complete like normal and the the second will be issued, but even though a response is sent back from the server the browser never actually displays the changes made to the contents of the updatepanel. Any ideas?

    As an aside, one (rather obvious) thing worth noting:

    On the following line
    argsQue.push(document.form1.__EVENTARGUMENT.value);
    should be something like
    argsQue.push(document.forms[0].__EVENTARGUMENT.value);
    (assuming that you only have one form on the page holding your controls)

    Comment by Dale | January 14, 2008 | Reply

  2. Dale:

    Thanks for the feedback. You are totally right about the forms collection. I never got around to fixing that from my test page. As for the sorts not queuing, I’d be interested if you could email me the page you are using. I think you must be getting an error from something else that is precluding the javascript from running.

    Comment by disturbedbuddha | January 15, 2008 | Reply

  3. […] have the following JS code extracted from the following link (http://disturbedbuddha.wordpress.com/2007/12/12/handling-multiple-asynchronous-postbacks/#comment-18…) var prm = Sys.WebForms.PageRequestManager.getInstance(); […]

    Pingback by How can I get the actual ID from get_postBackElement - ASP.NET Forums | May 6, 2009 | Reply

  4. Nice solution. Thanks.

    Comment by Sudesh Bainsla | November 9, 2009 | Reply

  5. hi,
    Your solution is nice,I have a problem.I have a list of Items in a page.Each item is in different update panel.Each item contains a button to select that item and do some database process.Now each process take time.I want to enable multiple postbacks to execute at the same time.Each button calls different methods.But When i am clicking on second update panel’s button my first requist will be canceled.Now if i am using your approch again my user should wait for the first process to complete.Wich is not really asyncronous.can we make multiple calls simultaniously from a page
    Any suggesion on this matter will be appreciated

    Comment by prasanth | April 29, 2010 | Reply

  6. Awesome solution. I faced that problem with multiple postbacks and your solution works perfect. Cheers, alex

    Comment by alex | September 14, 2010 | Reply

  7. You are really expert. “Very Good Article” i came across after so many research on Net. It opens the door to handle multiple asynch postbacks. Thanks very much.

    Thanks,
    Kalpesh

    Comment by Kalpesh Desai | December 26, 2011 | Reply

  8. cheers. worked for me perfect

    Comment by PP | November 1, 2012 | Reply

  9. My brother recommended I may like this web site. He used to be entirely right. This post actually made my day. You cann’t believe simply how a lot time I had spent for this information! Thank you!

    Comment by czeslawa | January 29, 2013 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: