我有一个页面,我使用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()));
}
重现的步骤:
答案 0 :(得分:5)
您正在同步调用该页面。您需要异步调用它,否则像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;
}
}