ASP.NET 2.0 Асинхронный пользовательский элемент управления не работает - PullRequest
4 голосов
/ 07 ноября 2008

Я пытаюсь заставить пользовательский элемент управления работать асинхронно, но независимо от того, что я делаю, он продолжает работать синхронно. Я сократил его до минимума в качестве тестового веб-приложения. Это будет пользовательский элемент управления:

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

И это будет страница, на которой я размещаю элемент управления три раза:

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

Страница отображается без ошибок, но трассировка внизу страницы показывает, что каждый экземпляр элемента управления обрабатывается синхронно. Что я делаю неправильно? Где-то мне не хватает настроек конфигурации?

Ответы [ 2 ]

7 голосов
/ 08 ноября 2008

Похоже, я могу ответить на свой вопрос. Пользовательский элемент управления не должен вызывать Page.ExecuteRegisteredAsyncTasks. После этого элемент управления добавил асинхронную задачу, запустил ее и ожидал ее завершения.

Вместо этого каждый экземпляр пользовательского элемента управления должен вызывать только Page.RegisterAsyncTask. После того, как каждый экземпляр элемента управления сделает это, страница автоматически вызывает RegistereAsyncTask, одновременно выполняющей все три зарегистрированные асинхронные задачи.

Итак, вот новый пользовательский элемент управления:

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

И неизменная страница, которая создает три экземпляра элемента управления:

<%@ 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>
1 голос
/ 08 марта 2011

Если я могу немного добавить к вышеприведенному посту, мы не должны называть ExecuteRegisteredAsyncTassk явно, если нет веской причины. после регистрации асинхронной задачи платформа ASP.NET выполнит все эти задачи сразу после события OnPrerender жизненного цикла страницы.

Примером использования ExecuteRegisteredAsyncTasks может быть; Иногда вам может потребоваться убедиться, что несколько асинхронных операций завершены, прежде чем вызывать другую асинхронную задачу. в такой ситуации оправданно использовать ExecuteRegisteredAsyncTasks.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...