试图使用asp.net异步页面

时间:2015-02-26 09:08:37

标签: c# asp.net asynchronous

我有一个ASP.NET(webforms)页面,需要调用一个可能需要一分钟才能返回的存储过程。我意识到这不是理想的,但是这个项目的数据库方面不在我手中,因此我必须忍受这个问题。

基本上我正在寻找一些方法,它允许页面在没有存储过程挂起页面的情况下呈现 - 数据库调用的结果在可用时显示。

所以,我正在查看异步页面。我添加了" ASYNC = TRUE"到页面顶部,到目前为止,我有以下内容:

private async void GetCampaignCounts(int CampaignID)
{
    Task t = new Task
    (
        () =>
        {

            CampaignService cs = new CampaignService();
            FilterSet.TargetCounts f = cs.GetCampaignDetails(CampaignID); //LONG RUNNING DB CALL

            if (f.Total > 0)
            {
                panelStatsLeft.Visible = true;

        //DO STUFF IN HERE
            }
            else
                panelStatsLeft.Visible = false;
        }
    );

    t.Start();
    await t;


}

但是,当数据库查询正在运行时,这仍会挂起页面!

我做错了什么?!

3 个答案:

答案 0 :(得分:0)

Web应用程序中的异步请求不是为了不挂起页面。该请求仍将与同步版本同时使用。优点在于可扩展性(即,如果您的页面可以处理100个并发用户,如果它在同一硬件上是异步的话,假设瓶颈是请求管道而不是数据库,那么它将能够处理1000个。)

如果你想在操作完成时加载页面并自行更新,恐怕你需要更复杂的架构。最好的办法是加载页面并执行运行查询的ajax请求,并在请求返回时更新页面。最佳做法是对此ajax请求使用async / await(同样是为了可伸缩性)。

答案 1 :(得分:0)

就个人而言,我并不打算将两者捆绑在一起。更好的操作是将查询卸载到其他地方并稍后返回以获得结果。

因此使用信号框架,如signalr。提交您的报告参数,将它们传递给msmq,在那里可以在不同的服务器上处理它们或使用单向wcf请求。当收到请求时,可选择将结果存储在数据库中,并使用信令通知客户端(向他们传递实际结果或告诉他们可以从中下载报告的URL(从其他URL中的数据库中提取)) 。异步进入用户当前的浏览器页面,其中可能有一个微调器说"嘿,我们正在生成您的报告"。

考虑发信号。

答案 2 :(得分:0)

正如我在关于该主题的MSDN文章中所述,async on ASP.NET is not a silver bullet

  

当一些开发人员了解异步并等待时,他们认为这是服务器代码“屈服”到客户端(例如,浏览器)的一种方式。但是,async和等待ASP.NET只能“屈服”到ASP.NET运行时; HTTP协议保持不变,每个请求仍然只有一个响应。如果在异步/等待之前需要SignalR或AJAX或UpdatePanel,则在异步/等待之后仍需要SignalR或AJAX或UpdatePanel。

如果您考虑HTTP协议,这是有道理的:每个请求只能有一个响应,async不会更改HTTP协议(更详细on my blog)。因此,如果您向客户端返回响应(允许它呈现页面),那么该请求就完成了。您以后无法发送后续回复来更改您已发送的页面。

正确的解决方案相当复杂,因为ASP.NET并未设计用于跟踪"背景"没有请求的操作。 ASP.NET将定期回收您的应用程序,如果没有活动请求,它会认为这是一个好时机。所以,"背景"操作有被终止的危险,恕不另行通知。

出于这个原因,最好的解决方案是拥有一个独立的工作进程,该进程实际使用基本的分布式体系结构执行后台操作(请求由ASP.NET处理程序放入可靠队列;请求将重新进入队列如果工作进程失败,则自动执行)。这也意味着您的请求应该是幂等的。

如果您不想要这种复杂程度,您可以权衡可靠性的复杂性。中间步骤是Hangfire,它至少需要一个数据库后端(它用于可靠性而不是队列)。如果您希望可靠性最低(且复杂性最低),则可以使用HostingEnvironment.QueueBackgroundWorkItemASP.NET Background Tasks library。我对这些选项on my blog进行了较长时间的概述。