使用BuildManager.CreateInstanceFromVirtualPath创建页面时,PageAsyncT

本文关键字:PageAsyncT BuildManager CreateInstanceFromVirtualPath 创建 使用 | 更新日期: 2023-09-27 18:10:49

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

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

复制示例:

TestPage.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>

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

复制步骤:

    导航到TestPage。Aspx,点击按钮&消息按预期出现导航到/TestHandler,你应该看到相同的页面,但是如果你点击按钮,消息不会出现。

使用BuildManager.CreateInstanceFromVirtualPath创建页面时,PageAsyncT

您正在同步调用Page。您需要异步调用它,否则需要异步api,如Page。RegisterAsyncTask将不能正常工作。试试这样做:

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