2010-08-25 63 views
2

在ASP.Net中,我想在页面已经发送给用户之后运行一些代码(日志记录,其他清理)。我不希望此代码干扰客户端接收响应所花费的时间。我试着将这段代码放在页面的OnUnload部分,但通过测试(使用断点或繁忙的等待循环),客户端实际上不显示页面,直到OnUnload中的代码完成执行。尽管此时响应对象不再可用,因此我会假设缓冲响应已发送到客户端,但客户端仍然不显示页面,直到OnUnload完成执行。似乎目前唯一可行的方法是启动一个新线程来完成工作,并允许OnUnload立即完成。但是,我不知道这是否安全。如果服务器在页面已经发出后执行太长时间,服务器是否会终止该线程?有没有更正确的方法来实现这一点?在ASP.Net中,如何在发送页面后运行代码

+1

你可以使用消息传递队列,并有一个后台进程照顾它吗?更像是一个Web角色和一个工作角色如何在Azure中彼此交互? – 2010-08-25 19:27:59

+0

我试图帮助downvote,但它看起来像某人真的不喜欢这个问题! – mclark1129 2010-08-25 19:35:13

+0

我通常会在没有回复的情况下删除这些问题,如果这些问题太长了。通常情况下,你以后不会得到一个,它有助于限制来自SO的未答复(并且基本上无用)问题的数量。 – mclark1129 2010-08-25 20:06:28

回答

1

卸载是ASP.NET页面生命周期的最后一部分。见下面的链接:

http://msdn.microsoft.com/en-us/library/ms178472.aspx

这是不是你可以用JavaScript或AJAX吗?

+0

我特别声明,我尝试使用Unload部分,并且浏览器仍然不显示页面,直到卸载代码完成。这不是我在Javascript或Ajax中可以做到的,因为它必须运行服务器端,并且我不能依赖于启用了Javascript的客户端来启动AJAX调用。 – Kibbee 2010-08-25 18:48:51

+1

Kibbee我读过,但是你没有说明你知道这是页面生命周期的最后阶段,这就是我提到它的原因。我不认为它值得-1,但如果你想要帮助你理解asp.net的工作原理,我肯定不会在你的任何问题上发布任何问题。 – 2010-08-25 18:52:53

+0

对不起,但我觉得downvote“这个答案没有用”的描述真的应用在这里。就我个人而言,我发现如果您实际上没有提供可以解决问题的信息,那么您应该将其作为评论。你给的答案只是额外的信息。它不能解决我所遇到的问题。 – Kibbee 2010-08-25 18:59:28

0

如何挂钩到page.Disposed事件而不是Unload事件?

+0

试了一下。看起来像在代码执行之前发送页面时,我现在面临的问题是它看起来代码根本没有运行。虽然它可能会在将来运行,当物体本身被处置时。我希望代码能够以更及时的方式执行,而不是当它处理对象时。 – Kibbee 2010-08-25 19:49:55

0

根据您需要做什么,可以创建一个ISAPI过滤器,以在响应结束时执行某些操作。

2

基比,

尝试重写Page.Render方法和冲洗,像这样的回应:

Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter) 
    MyBase.Render(writer) 

    Response.Flush() ' Sends all buffered output to the client 

    ' Run some code after user gets their content 
End Sub 

我觉得在这一点上仍然反应是不完整的,但用户会得到什么在完成最终代码的运行之前,该页面已经呈现。

HTH,

迈克

+0

这按预期工作。利用Repsonse对象,我可以让浏览器接收并呈现内容。然而,问题在于浏览器页面仍显示为加载(旋转图标/小时玻璃),与页面加载时类似,即使在收到内容之后。即使在Response.Flush()之后添加Response.Close之后,此行为仍然存在。也很高兴看到在VB.Net中编码的其他人。似乎.NET中的大部分内容都集中在C#上。 – Kibbee 2010-08-25 23:32:23

+0

我非常肯定,直到整个ASP.net生命周期完成执行,响应才能完全关闭。这包括HAPPApplication.EndRequest事件,其中AFIAK是生命周期中绝对的最后一点(不计算应用程序何时结束)。我认为上述方法将会在不产生新线程的情况下最接近你想要的。如果你使用多线程,那么我建议在HttpApplication.EndRequest中产生线程,以避免线程在Response.End()中被中止。 – mclark1129 2010-08-26 18:59:53

0

你可以试试这个解决方案 - Best ASP.NET Background Service Implementation

使用Windows服务并与之连通的通MSMQ可能是一个更为可靠的解决方案,并可以扩展更好。这将帮助您分离问题,并让asp.net前端专注于用户,而Windows服务专注于后台任务。

如果您正在使用Azure迁移到云,您可以简单地将asp.net前端替换为Web角色,并且带有工作角色和您的解决方案的Windows服务可以无缝扩展!

0

下面是一个重做方式来做到这一点。有第二个aspx页面,完成所有“清理”后渲染逻辑。例如,调用一个'cleanup.aspx'。在Page_Load中运行cleanup.aspx你的清理代码:

public partial class cleanup: System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     // do logging blah blah here.... 
    } 
} 

在您的主aspx页面,有一个JavaScript函数,使一个AJAX调用“cleanup.aspx”。加载页面后启用AJAX功能。我建议jQuery的,如果是你的代码看起来就像这样:

$(function(){ 
    yourAJAXYFunctionName(); 
}); 

function yourAJAXYFunctionName()() { 
// ajax code here 
// 
$.ajax({ 
    url: "cleanup.aspx", 
    }); 
} 

这样,你的第一页的代码运行,然后在页面发送给浏览器。当页面呈现给客户端时,第二个ASPX页面通过AJAX调用,这对于cleanup.aspx并不重要,它并不在乎它的被调用和页面加载事件是如何执行的。然后运行您的清理/日志记录代码。

注意事项:客户端JavaScript是必需的。但是真的到底谁没有JS呢?另外,您的cleanup.aspx页面完全从您的主页面中抽象出来,因此如果您想要使用源于第一页的cleanup.aspx中的任何对象,那么您必须将它们存储在会话或cookie中,或者您可以在AJAX调用中将它们作为参数传递。这需要动态操作AJAX脚本本身,但这并不难。

-1

更好的我想尝试{Response.End()} catch {} runco​​de();

+1

这不是现在状态下的答案。请重新格式化。 – simonmorley 2014-08-21 22:38:18

相关问题