2

我有一个页面,我添加了一个异步任务,使用Page.RegisterAsyncTask. 如果页面可以正常访问,例如通过导航到“/foo.aspx”,那么一切都按预期工作。该应用程序有一些相当复杂的路由,在某些情况下,页面是从一个调用BuildManager.CreateInstanceFromVirtualPath("~/foo.aspx", typeof(Page)) as IHttpHandler然后调用ProcessRequest结果处理程序的处理程序创建的。看起来页面在完成之前没有等待注册任务完成。

在这种情况下,如何让页面等待异步任务完成?

复制样本:

测试页.aspx:

<%@ Page Language="C#" AutoEventWireup="true" Inherits="WebApplication1.TestPage" Async="true" AsyncTimeout="60" MasterPageFile="~/Site.Master" %>

<asp:Content ContentPlaceHolderID="MainContent" runat="server">
    <asp:Button Text="Do Stuff" OnClick="Button1_Click" ID="Button1" runat="server" />
    <asp:Literal ID="ResultsLiteral" runat="server" />

    <script runat="server">
        protected void Button1_Click(object sender, EventArgs e)
        {
            RegisterAsyncTask(new PageAsyncTask(DoStuff));
        }

        async System.Threading.Tasks.Task DoStuff()
        {
            await System.Threading.Tasks.Task.Delay(5);
            ResultsLiteral.Text = "Done";
        }
    </script>
</asp:Content>

测试处理器.cs

using System.Web;
using System.Web.Compilation;
using System.Web.Routing;
using System.Web.UI;

namespace WebApplication1
{
    public class TestHandler : IHttpHandler
    {
        public bool IsReusable
        {
            get { return false; }
        }

        public void ProcessRequest(HttpContext context)
        {
            GetHttpHandler().ProcessRequest(context);
        }

        IHttpHandler GetHttpHandler(HttpContext context)
        {
            return BuildManager.CreateInstanceFromVirtualPath("~/TestPage.aspx", typeof(Page)) as IHttpHandler;
        }
    }

    public class RouteHandler : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext context)
        {
            return new TestHandler();
        }
    }
}

路由(在 RouteConfig.cs 中添加):

public static void RegisterRoutes(RouteCollection routes)
{
    routes.Add(new Route("TestHandler", new RouteHandler()));
}

重现步骤:

  1. 导航到 TestPage.aspx,单击按钮并按预期显示消息
  2. 导航到 /TestHandler,您应该会看到相同的页面,但是如果您单击该按钮,则不会出现该消息。
4

1 回答 1

5

您正在同步调用 Page 。您需要异步调用它,否则 Page.RegisterAsyncTask 之类的异步 API 将无法正常运行。尝试这样的事情:

public class TestHandler : IHttpAsyncHandler
{
    private IHttpAsyncHandler _handler;

    public bool IsReusable
    {
        get { return false; }
    }

    public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback callback, object state)
    {
        _handler = GetHttpHandler(context);
        return _handler.BeginProcessRequest(context, callback, state);
    }

    public void EndProcessRequest(IAsyncResult asyncResult)
    {
        _handler.EndProcessRequest(asyncResult);
    }

    public void ProcessRequest(HttpContext context)
    {
        throw new NotSupportedException();
    }

    IHttpAsyncHandler GetHttpHandler(HttpContext context)
    {
        return BuildManager.CreateInstanceFromVirtualPath("~/TestPage.aspx", typeof(Page)) as IHttpAsyncHandler;
    }
}
于 2014-07-01T05:23:11.557 回答