代码之家  ›  专栏  ›  技术社区  ›  Giovanni Galbo

ASP.net webforms(.net 2.0)中异步页处理的示例

  •  8
  • Giovanni Galbo  · 技术社区  · 13 年前

    有人能给我提供一个在ASP.NET Webforms 2.0中异步页面处理的简单例子吗(我正在使用VS 2010,所以像lambdas这样的新语法就可以了)?

    我有一些长时间运行的请求,我不想占用IIS线程。

    为了简单起见,假设我当前的代码如下所示:

    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);
    
    }
    

    如何修改此代码以使其异步?假设我已经在aspx页面中设置了async=“true”。

    编辑

    我想我找到了我想要的东西。我把示例代码放在了一个答案中 here . 请随时指出任何可能出现的缺陷或变化。

    3 回复  |  直到 7 年前
        1
  •  16
  •   BoltClock    12 年前

    我问了一些ASP.NET团队的人。这是他们给我和你的邮件回复。

    代码最终所做的就是旋转一个新线程并在该线程上执行委托调用。现在有两个线程在运行:请求线程和新线程。因此,此示例的性能实际上比原始同步代码的性能差。

    http://www.asp.net/web-forms/tutorials/aspnet-45/using-asynchronous-methods-in-aspnet-45 有关如何在ASP.NET中编写和使用异步方法的示例。

        2
  •  6
  •   jessegavin    13 年前

    下面是异步处理的一个简单示例。

       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.");
        }
    

    其他方式

    您可以使用PageAsyncTask,请参见下面的完整示例:
    http://msdn.microsoft.com/en-us/library/system.web.ui.pageasynctask.aspx

    有点像

    clAsynCustomObject oAsynRun = new clAsynCustomObject();
    
    PageAsyncTask asyncTask = new PageAsyncTask(oAsynRun.OnBegin, oAsynRun.OnEnd, oAsynRun.OnTimeout, null, true);
    Page.RegisterAsyncTask(asyncTask);
    Page.ExecuteRegisteredAsyncTasks();
    
        3
  •  0
  •   Community Egal    7 年前

    我想我发现了如何做我想做的事。。。尽管这可能不是最好的方式,但请随时插话。

    在写这篇文章的时候,只有一个答案, by Aristos . 虽然他给出了一个执行异步请求的示例,但我想要的是告诉ASP.NET执行一些长时间运行的方法,释放IIS线程以便它可以服务于其他请求,然后在方法完成时返回。

    下面是我用同样(或类似)的例子提出的问题:

    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();
            }
        }
    }