4

ユーザーコントロールを非同期で動作させようとしていますが、何をしても同期的に動作し続けます。テスト用の Web アプリケーションとして、必要最小限のものまで取り除いてあります。これはユーザー コントロールになります。

<%@ Control Language="C#" %>
<script runat="server">
    SqlConnection m_oConnection;
    SqlCommand    m_oCommand;

    void Page_Load(object sender, EventArgs e)
    {
        Trace.Warn("Page_Load");
        string strDSN = ConfigurationManager.ConnectionStrings["DSN"].ConnectionString + ";async=true";
        string strSQL = "waitfor delay '00:00:10'; select * from MyTable";

        m_oConnection = new SqlConnection(strDSN);
        m_oCommand = new SqlCommand(strSQL, m_oConnection);
        m_oConnection.Open();

        Page.RegisterAsyncTask(new PageAsyncTask(new BeginEventHandler(BeginHandler), new EndEventHandler(EndHandler), new EndEventHandler(TimeoutHandler), null, true));
        Page.ExecuteRegisteredAsyncTasks();
    }

    IAsyncResult BeginHandler(object src, EventArgs e, AsyncCallback cb, object state)
    {
        Trace.Warn("BeginHandler");
        return m_oCommand.BeginExecuteReader(cb, state);
    }

    void EndHandler(IAsyncResult ar)
    {
        Trace.Warn("EndHandler");
        GridView1.DataSource = m_oCommand.EndExecuteReader(ar);
        GridView1.DataBind();
        m_oConnection.Close();
    }

    void TimeoutHandler(IAsyncResult ar)
    {
        Trace.Warn("TimeoutHandler");
    }
</script>
<asp:gridview id="GridView1" runat="server" />

これは、コントロールを 3 回ホストするページです。

<%@ page language="C#" trace="true" async="true" asynctimeout="60" %>
<%@ register tagprefix="uc" tagname="mycontrol" src="~/MyControl.ascx" %>
<html>
    <body>
        <form id="form1" runat="server">
            <uc:mycontrol id="MyControl1" runat="server" />
            <uc:mycontrol id="MyControl2" runat="server" />
            <uc:mycontrol id="MyControl3" runat="server" />
        </form>
    </body>
</html>

ページはエラーなしで表示されますが、ページの下部にあるトレースは、各コントロール インスタンスが同期的に処理されていることを示しています。私は何を間違っていますか?不足している構成設定はありますか?

4

2 に答える 2

7

自分の質問に答えることができるようです。ユーザー コントロールは を呼び出してはなりませんPage.ExecuteRegisteredAsyncTasks。これにより、コントロールは非同期タスクを追加して実行し、完了するまで待機していました。

代わりに、ユーザー コントロールの各インスタンスは のみを呼び出す必要がありますPage.RegisterAsyncTask。各コントロール インスタンスがこれを行った後、ページは、RegistereAsyncTask登録されている 3 つの非同期タスクを同時に実行することを自動的に呼び出します。

これが新しいユーザー コントロールです。

<%@ Control Language="C#" %>
<script runat="server">
    SqlConnection m_oConnection;
    SqlCommand    m_oCommand;

    void Page_Load(object sender, EventArgs e)
    {
        Trace.Warn(ID, "Page_Load - " + Thread.CurrentThread.GetHashCode().ToString());
        string strDSN = ConfigurationManager.ConnectionStrings["DSN"].ConnectionString + ";async=true";
        string strSQL = "waitfor delay '00:00:10'; select * from TEProcessedPerDay where Date > dateadd(day, -90, getutcdate()) order by Date asc";

        m_oConnection = new SqlConnection(strDSN);
        m_oCommand = new SqlCommand(strSQL, m_oConnection);
        m_oConnection.Open();

        Page.RegisterAsyncTask(new PageAsyncTask(new BeginEventHandler(BeginHandler), new EndEventHandler(EndHandler), new EndEventHandler(TimeoutHandler), null, true));
    }

    IAsyncResult BeginHandler(object src, EventArgs e, AsyncCallback cb, object state)
    {
        Trace.Warn(ID, "BeginHandler - " + Thread.CurrentThread.GetHashCode().ToString());
        return m_oCommand.BeginExecuteReader(cb, state);
    }

    void EndHandler(IAsyncResult ar)
    {
        Trace.Warn(ID, "EndHandler - " + Thread.CurrentThread.GetHashCode().ToString());
        GridView1.DataSource = m_oCommand.EndExecuteReader(ar);
        GridView1.DataBind();
        m_oConnection.Close();
    }

    void TimeoutHandler(IAsyncResult ar)
    {
        Trace.Warn(ID, "TimeoutHandler - " + Thread.CurrentThread.GetHashCode().ToString());
    }
</script>
<asp:gridview id="GridView1" runat="server" />

そして、コントロールの 3 つのインスタンスを作成する変更されていないページ:

<%@ page language="C#" async="true" trace="true" %>
<%@ register tagprefix="uc" tagname="mycontrol" src="~/MyControl.ascx" %>
<html>
    <body>
        <form id="form1" runat="server">
            <uc:mycontrol id="MyControl1" runat="server" />
            <uc:mycontrol id="MyControl2" runat="server" />
            <uc:mycontrol id="MyControl3" runat="server" />
        </form>
    </body>
</html>
于 2008-11-07T21:36:06.300 に答える
1

上記の投稿に少し付け加えるとしたらExecuteRegisteredAsyncTassk、やむを得ない理由がない限り、 を明示的に呼び出すべきではありません。OnPrerender非同期タスクを登録すると、ASP.NET フレームワークは、ページ ライフサイクルのイベントの直後にこれらすべてのタスクを実行します。

の使用例は次のとおりExecuteRegisteredAsyncTasksです。別の非同期タスクを呼び出す前に、いくつかの非同期操作が完了していることを確認する必要がある場合があります。このような状況では、 を使用するのが正当ExecuteRegisteredAsyncTasksです。

于 2011-03-08T08:09:55.957 に答える