2

を使用して、非同期タスクを追加したページがあります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()));
}

再現する手順:

  1. TestPage.aspx に移動し、ボタンをクリックすると、期待どおりにメッセージが表示されます
  2. /TestHandler に移動すると、同じページが表示されますが、ボタンをクリックしてもメッセージは表示されません。
4

1 に答える 1

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;
    }
}
于 2014-07-01T05:23:11.557 に答える