假设异步页的后台代码如下,我将BeginAsyncOperation方法中的代码
cb(t);
注释掉后,访问该异步页时,就陷入长期的等待中。我的问题是:为什么会这样?我猜测:
    HttpRuntime在执行异步调用时,负责激活异步调用的主方法,
在激活BeginEventHandler代理的方法后,就处于等待状态。
    而能够结束等待状态的条件就是:所有注册了异步执行的方法都已成功返回,
或者执行注销。
    要做到这些,就要求在异步线程中返回一个结束信号。
这个结束信号由执行BeginAsyncOperation方法中的参数AsyncCallback cb
所包含的代理方法后发出,而不是BeginAsyncOperation方法的返回值。
    这也说明,BeginAsyncOperation代理的BeginAsyncOperation方法的返回值IAsyncResult对象,
并不能告诉ASP.NET:我的任务完成了。
    可是很奇怪,这个返回值到底有什么用?如何使用?
       
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;public partial class _Default : System.Web.UI.Page 
{
    int i;
    string ii;    void Page_Load(object sender, EventArgs e)
    {
        AddOnPreRenderCompleteAsync(
            new BeginEventHandler(BeginAsyncOperation),
            new EndEventHandler(EndAsyncOperation)
         );
    }    IAsyncResult BeginAsyncOperation(object sender, EventArgs e, AsyncCallback cb, object state)
    {
        i++;
        AsyncResult t = new AsyncResult();
        t.IsCompleted = true;//不论设定false还是true,结果相同
        //cb(t);
        return t;
    }
    void EndAsyncOperation(IAsyncResult ar)
    {
        ii = i.ToString();
    }    protected void Page_PreRenderComplete(object sender, EventArgs e)
    {
        Label1.Text = ii;
    }
}public class AsyncResult : IAsyncResult
    {
        private object _asyncState;
        private bool _isCompleted;        public AsyncResult()  {    }        public object AsyncState
        {
            get { return this._asyncState; }
            set { this._asyncState = value; }
        }        public bool IsCompleted
        {
            get { return this._isCompleted; }
            set { this._isCompleted = value;  }
        }        object IAsyncResult.AsyncState
        {  get {   return this._asyncState;  } }        WaitHandle IAsyncResult.AsyncWaitHandle
        {  get {  return null;  }  }        bool IAsyncResult.CompletedSynchronously
        {   get {  return false;    }  }        bool IAsyncResult.IsCompleted
        {   get   {  return this._isCompleted;   }   }
    }

解决方案 »

  1.   

    你可以先看一下MSDN上的示例.
    Asynchronous Pages in ASP.NET 2.0
    如果cb(t)不调用,那么EndAsyncOperation根本就不会被调用到,阻塞是必然.
    我没有去确定cb是不是就是EndAsyncOperation,但是
    AsyncCallback的委托声明跟EndAsyncOperation这个方法是匹配的.你可以在调试的时候在
    return t;
    处设置一个断点,然后在
    ii = i.ToString();
    设置另一个断点,如果是调用了cb(t),你会发现程序会在后一个断点处先停住,F5继续之后会在前一个断点停住.
    cb这个异步的操作是让另一个异步操作去做回调的,在这个异步操作执行完成之后,来执行cb,
    因此cb绝对不该在BeginAsyncOperation被主动调用.
      

  2.   

    你的意思我明白
    但解决不了我的追究我看了反编译代码,调用过程很难跟踪。所以,放弃了。
    但我从多方面的其他研究得出一个结论:
    异步事件虽然与异步执行相关,但执行的过程受到ASP.NET的机制所控制,不能等同于异步执行。同时,异步事件的begin方法的委托参数AsyncCallback cb必须被调用,才能使异步事件完成回调。具体原理必须从微软的相关类库的源代码中寻求答案。