views:

1909

answers:

1

I'm trying to get a user control working asynchronously, yet no matter what I do it continues to work synchronously. I've stripped it down to its bare minimum as a test web application. This would be the user control:

<%@ 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" />

And this would be the page in which I host the control three times:

<%@ 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>

The page gets displayed without errors, but the trace at the bottom of the page shows each control instance is processed synchronously. What am I doing wrong? Is there a configuration setting somewhere I'm missing?

+3  A: 

Looks like I can answer my own question. The user control should not be calling Page.ExecuteRegisteredAsyncTasks. By doing that, the control was adding the async task, running it, and waiting for it to complete.

Instead, each instance of the user control should call only Page.RegisterAsyncTask. After each control instance has done this the page automatically calls RegistereAsyncTask running all three registered async tasks simultaniously.

So here is the new user control:

<%@ 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" />

And the unchanged page that creates three instances of the control:

<%@ 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>
Charles