开发者

Example of Asynchronous page processing in ASP.net webforms (.NET 2.0)

开发者 https://www.devze.com 2023-01-25 01:38 出处:网络
Can someone provide me with a simple example of Asynchronous page processing in ASP.NET Webforms 2.0 (I\'m using VS 2010, so new syntax like lambdas are ok)?

Can someone provide me with a simple example of Asynchronous page processing in ASP.NET Webforms 2.0 (I'm using VS 2010, so new syntax like lambdas are ok)?

I have some long running requests that I don't want tying up IIS threads.

For simplicity's sake, let's say my current code looks like this:

protected void Page_Load(object sender, EventArgs e)
{
    string param1 = _txtParam1.Text;
    string param2 = _txtParam2.Text;

    //This takes a long time (relative to a web request)
    List<MyEntity> entities = _myRepository.GetEntities(param1, param2);

    //Conceptually, I would like IIS to bring up a new thread here so that I can
    //display the data after it has come back.
    DoStuffWithEntities(entities);

}

How can I modify this code so that it is asynchronous? Let's assume that I already set async="true" in the aspx page.

EDIT

开发者_开发问答

I think I figured out how to get what I'm looking for. I've put the example code in an answer here. Feel free to point out any flaws or changes that can be made.


I asked some folks on the ASP.NET team. Here's their emailed response to me, and now, to you.

All that code ends up doing is spinning up a new thread and performing delegate invocation on that thread. So now there are two threads running: the request thread and the new thread. Hence this sample actually has worse performance than the original synchronous code would have had.

See http://www.asp.net/web-forms/tutorials/aspnet-45/using-asynchronous-methods-in-aspnet-45 for a sample on how to write and consume async methods in ASP.NET.


Here is a simple example of asynchronous processing.

   protected void Page_Load(object sender, EventArgs e)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
        ThreadPool.QueueUserWorkItem(state => Dokimes_Programming_multithread_QueryWorkThead.ThreadProc2());

        Debug.Write("Main thread does some work, then sleeps.");
        // If you comment out the Sleep, the main thread exits before
        // the thread pool task runs.  The thread pool uses background
        // threads, which do not keep the application running.  (This
        // is a simple example of a race condition.)
        // Thread.Sleep(4000);

        txtDebug.Text += "ended";

        Debug.Write("end.");
    }


    // This thread procedure performs the task.
    static void ThreadProc(Object stateInfo)
    {

        // No state object was passed to QueueUserWorkItem, so  stateInfo is null.
        Debug.Write(" Hello from the thread pool 1.");
    }

    static void ThreadProc2()
    {
        // No state object was passed to QueueUserWorkItem, so  stateInfo is null.
        Debug.Write("Hello from the thread pool 2.");
    }

Other way

You can use the PageAsyncTask, see here a full example:
http://msdn.microsoft.com/en-us/library/system.web.ui.pageasynctask.aspx

Something like

clAsynCustomObject oAsynRun = new clAsynCustomObject();

PageAsyncTask asyncTask = new PageAsyncTask(oAsynRun.OnBegin, oAsynRun.OnEnd, oAsynRun.OnTimeout, null, true);
Page.RegisterAsyncTask(asyncTask);
Page.ExecuteRegisteredAsyncTasks();


I think I discovered how to do what I wanted to accomplish... though it may not be the best way, feel free to chime in.

At the time of writing there was only one answer in this thread, by Aristos. While he gave an example of executing an asynchronous request, what I wanted was a way to tell ASP.NET to execute some long running method, release the IIS thread so it can be available to service other requests, and then come back when the method finished.

Here's what I came up with, using the same (or similar) example in the question:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Web.UI;

namespace WebApplication2
{
    public class MyEntity
    {
        public string Name { get; set; }
    }

    public class MyRepository
    {
        public List<MyEntity> GetEntities(string param1, string param2)
        {
            Thread.Sleep(10000);
            return new List<MyEntity> {new MyEntity {Name = "John Smith"}};
        }
    }

    public partial class Default : Page
    {
        private readonly MyRepository _myRepository = new MyRepository();
        private List<MyEntity> _myEntities;

        protected void Page_Load(object sender, EventArgs e)
        {
        }

        private void DoStuffWithEntities()
        {
            Response.Write("<br/><br/><b>" + _myEntities[0].Name + "</b><br/><br/>");
        }

        protected void _btnProcess_Click(object sender, EventArgs e)
        {
            AddOnPreRenderCompleteAsync(BeginExecution, EndExecution, null);
        }

        private void GetEntities()
        {
            string param1 = _txtParam1.Text;
            string param2 = _txtParam2.Text;


            //This takes a long time (relative to a web request)
            _myEntities = _myRepository.GetEntities(param1, param2);
        }

        private IAsyncResult BeginExecution(object sender, EventArgs e, AsyncCallback callback, object state)
        {
            var t = new ThreadStart(GetEntities);
            return t.BeginInvoke(callback, null);
        }

        private void EndExecution(IAsyncResult result)
        {
            //Conceptually, I would like IIS to bring up a new thread here so that I can
            //display the data after it has come back.
            DoStuffWithEntities();
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消