【问题标题】:ASP.NET 2.0 Asynchronous User Control Not WorkingASP.NET 2.0 异步用户控件不起作用
【发布时间】:2010-09-21 08:58:12
【问题描述】:

我试图让用户控件异步工作,但无论我做什么,它都会继续同步工作。作为测试 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" />

这将是我在其中托管控件三次的页面:

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

页面显示没有错误,但页面底部的跟踪显示每个控件实例是同步处理的。我究竟做错了什么?是否有我缺少的配置设置?

【问题讨论】:

    标签: asp.net user-controls asynchronous


    【解决方案1】:

    如果我可以在上面的帖子中补充一点,我们不应该明确调用ExecuteRegisteredAsyncTassk,除非有令人信服的理由。注册异步任务后,ASP.NET 框架将在页面生命周期的OnPrerender 事件之后立即执行所有这些任务。

    ExecuteRegisteredAsyncTasks 的用法示例可以是: 有时您可能需要确保在调用另一个异步任务之前完成了几个异步操作。在这种情况下,使用ExecuteRegisteredAsyncTasks 是合理的。

    【讨论】:

      【解决方案2】:

      看来我可以回答我自己的问题了。用户控件不应调用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>
      

      【讨论】:

      • mate.. 即使不使用“ExecuteRegisteredAsyncTasks”,我的仍然无法正常工作。该页面仍在等待用户控件完成.. 有什么想法吗?
      • 那么如果你想在页面渲染后异步执行一些东西呢?例如,搜索页面...您只想从可能长时间运行的查询中更新搜索结果 UpdatePanel [Ajax]。
      • 我正在尝试做同样的事情,但就像 user384080 一样,我发现我的代码以及上面的代码同步运行。我只是相同的代码,但只是更改了对数据库的调用,睡眠时间为 2 秒。加载页面需要 2n 秒,其中 n=控件实例的数量,如果您查看跟踪,它们都在串行运行。
      • 编辑:没关系我是个白痴。我以为我已经注释掉了 ExecuteRegisteredAsyncTasks 行,但我没有。现在工作。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 1970-01-01
      • 1970-01-01
      • 2017-11-10
      • 1970-01-01
      相关资源
      最近更新 更多