//定义委托
public delegate void AsyncDelegate(string year, string month, string path);//异步调用
btnBuild.Enabled = false;
AsyncDelegate dlgt = new AsyncDelegate(CreateMonthReport);
IAsyncResult ar = dlgt.BeginInvoke(year, month, path, new AsyncCallback(CallbackMethod), dlgt);//回调方法
public void CallbackMethod(IAsyncResult ar)
{
     AsyncDelegate dlgt = (AsyncDelegate)ar.AsyncState;
     dlgt.EndInvoke(ar);     if (ar.IsCompleted)
     {
          btnBuild.Enabled = true;
     }
}现在我碰到的问题是:
CallbackMethod方法能够执行,btnBuild.Enabled = true语句也能执行到,可就是在页面上,它的状态始终不变化???还是btnBuild.Enabled = false的状态。郁闷ing,高手帮忙。

解决方案 »

  1.   

    主线程已经返回了.当前的httpcontext捕捉不到了.
      

  2.   

    为什么要在web中使用服务端的异步?
      

  3.   

    就是因为是WebForm所以你不能使用委托,不能在服务器端使用异步线程去操作用户的UI显示 " btnBuild.Enabled = true;"这个是不生效的,因为Http是短连接,一旦完成响应客户端请求的任务就会断开与客户端的连接.如果想要延迟,或者后台异步,请使用ajax.
      

  4.   

    等你回调的时候,web线程早就执行完了
      

  5.   

    慕白兄:
    情况是这样的:帮客户做一个内部使用的网站,其中有需要生成月报的这样一个操作,这个操作比较费时,代码执行下来的话,要两三分钟(具体在优化中,但是以客户的要求,也优化不了多少),所以客户就说那就用异步吧。
    再来介绍一下这个客户,他是做技术出身的,对于这个网站的实现,好多是我们以他的想法为主,因为他说这样实现好,就很难更改,没办法,“拿人钱财”嘛。慕白兄,
    你说的“主线程已经返回了.当前的httpcontext捕捉不到了.”,我刚刚在回调方法里写了System.Web.HttpContext.Current.Response.Redirect("abc.aspx")这种代码,System.Web.HttpContext.Current确实是Null的有什么方法吗?指教
      

  6.   

    所以客户就说那就用异步吧。--------------------------web中 异步调用还是用ajax吧。2-3分钟那有 10多万的数据?导入1张excel中的表? 不至于吧
      

  7.   

    如果你 不想得到返回结果。你可以把1次 分成 3次,甚至更多。向3个 ajax页面发送 处理请求,3个页面分别操作 对应插入 sheet1 sheet2 sheet3这就快多了。
      

  8.   

    不论什么ajax还是简单的页面自我回发(使用setTimeout触发),其实都是一样。异步就不是一次访问,看来你们完全没有理解客户说的是什么。web的访问是“一问一答”的机制,你的客户不希望在访问服务器时页面被服务器“拖死”,那么很自然这就意味着你根本不可能在这次访问的回答中看到委托执行的结果。了解asp.net页面生命周期模型,再写asp.net程序嘛!
      

  9.   

    让我们考虑一个最低级原始的asp.net页面,它在用户输入计算条件然后点“查看报表”按钮时,开始一个异步的计算任务(将任务的索引信息使用ViewState保存),然后将所有输入条件的部分变为Enabled=false的状态,然后取得此任务的进度信息(例如百分率)返回。因此用户在点击了按钮了之后1、2秒钟,所看到的页面反馈只是知道报表开始计算了。然后当用户再次按“查看报表”按钮时,程序根据任务索引取出任务的最新进度,显示新的进度。如果进度达到了100%,就取出最终产生的报表内容显示,并从ViewState中删除任务索引信息(显然任务已经不存在,或者即使存在也不需要访问了)。
    当然,这是手工去操作。而改为定时刷新,不算什么技术活。
      

  10.   

    非常感谢gongsun、sp1234的回答!
    针对“Lost_painting”的“因为Http是短连接,一旦完成响应客户端请求的任务就会断开与客户端的连接”,那么我是否可以在我的回调函数里再调用一次请求,然后把设置按钮可见性的语句放在这个按钮的Click事件里,代码如://回调方法
    public void CallbackMethod(IAsyncResult ar)
    {
         AsyncDelegate dlgt = (AsyncDelegate)ar.AsyncState;
         dlgt.EndInvoke(ar);     if (ar.IsCompleted)
         {
             btnSet_Click(btnSet,new EventArgs()); 
         }
    }public void btnSet_Click(object sender,EventArgs e)
    {
        btnBuild.Enable=false;
    }
    写法大致这样吧,没在编译器中,不知道正确与否,望高手指点
      

  11.   

    用另外一个ajax请求来获取执行进度?
      

  12.   

    sp1234,你说的这些我理解,我也理解客户说的内容,但是有一点,客户说他如果在页面上点了那个按钮,但是他确实不想离开页面,在这个页面上等待执行结果,但又不影响他在这个页面上做其它的操作,那么我该如何处理呢?
    ----------------------------
    很简单
    你可以在用户的这个页面里面,使用AJAX,当他点击按钮的时候,仍然是禁用按钮,在点击按钮的事件里面,使用脚本异步调用的方式,向服务器发送一个请求,而你可以在被请求的页面,执行你原来的所有语句让它计算,当计算完毕,返回给调用者一个信号,脚本接收到这个信号时,知道服务端已经OK了,此时可将按钮解除禁用,并通知用户(脚本弹出):报表已经生成好了.脚本方面的异步,你可使用jquery来实现,还是比较容易的
    下面是一个示例的简单代码
    <input type=button onclick="f();">
    <script language=javascript>
    function f()
    {
    $.ajax(
    {
    url: "你要执行报表生成的页面地址,可直接在地址后加参数",
    type: 'Post',
    async: true,
    cache: true,
    success: function(html)
    {
    //HTML就是你生成报表页面返回的信号
    if(html == "OK")
    {
    alert("告诉用户:报表已经生成好了");
    }
    else
    {
    //错误
    }
    }
    });
    }
    </script>在生成报表的页面中,生成完成之后,如下输出
    string xx = "OK";
    this.Response.Clear();
    this.Response.Write(xx);
    this.Response.End();当然,你可以输出更多信息,在客户端使用脚本拆分也可.但一定要遵循上述写法.