这是规格:

  • 使用 ASP.NET AJAX 的 ASP.NET 3.5
  • AJAX 控制工具包
  • jQuery 1.3.2
  • 网页服务
  • Windows Server 2003 SP1 上的 IIS6
  • SP1 SQLServer 2005 SP3 站点是 SSL
  • 基础设施网络组件 2009 年卷。2(使用非合气道控件),主要使用UltraWebGrid和Tree控件。

问题是这样的:我在 IE 7/8 中遇到白屏死机 (WSOD)。基本上,我有一个页面,其左窗格具有 AJAXControl Toolkit Accordion 控件,其中每个手风琴窗格内容都是 Infragistics 树控件。右侧窗格是 <div> 有一个 <iframe> 其内容根据左侧菜单窗格中的单击内容重新加载。

在里面 <iframe>, ,当您单击左窗格中的菜单项时,会加载一个包含一个或多个 UltraWebGrid 控件的页面。网格都有一个模板化按钮列。当您单击网格行的编辑按钮时,将打开一个用于编辑记录的弹出窗口。这种方法大约可以正常工作十次,然后在第十次(有时更早)时,弹出窗口将打开,地址栏中显示正确的 URL,但页面从未加载。

我们有一个应用程序,它使用一个弹出窗口来更新记录。大多数情况下,当您单击[编辑]按钮编辑记录时,会打开弹出窗口并加载更新页面。然而,编辑记录一段时间后,突然会打开弹出窗口,但它保持空白并挂起。URL 在地址栏中。

加载 Fiddler 我注意到更新页面的请求从未发送,这让我相信这是客户端的某种锁定。如果我将弹出窗口中的相同 URL 复制到新的浏览器窗口中,页面通常会正常加载。

观察结果:- 由于请求永远不会发送到服务器,因此它肯定与客户端或浏览器相关。- 仅在网站上有一些流量时才发生,这很奇怪,因为这似乎包含在客户端代码中 - 每隔几秒钟就会在后台调用一个Web服务,检查是否登录了用户是否登录了用户,但这不会导致冻结。

我真的很不知所措。我用 google 搜索过 WSOD,但似乎与我的特定 WSOD 相关的不多。有任何想法吗?

问题到底是什么

所以事实证明内存泄漏(尽管我已经在客户端密封了一些)不是问题。问题是在客户端进行 Web 服务调用。其中每 4 秒检查一次用户是否登录(以与另一个窗口同步),然后调用 Web 服务来获取用户对弹出窗口和网格状态的首选项。据我所知,Web 服务必须是异步的。我通过使用成功/失败回调从 JavaScript 调用它们来假设它们是异步的,但实际上不是。从客户端/浏览器的角度来看,它们是异步的,但从服务器端来看,会对 Web 服务进行调用,并在完成后返回,因为连接数量有限,因此会阻止任何其他操作。

那么使 Web 服务方法异步的最简单方法是什么?Web 服务是否需要转换为 WCF Web 服务,或者我可以使用现有的 ASP.NET Web 服务调用吗?

出于历史目的,我最初认为问题是这样的:

我无法在本地或我们的测试服务器上重现这一点。然而,我让 Fiddler 来模拟调制解调器速度,突然间我可以在本地 PC 上复制 WSOD。因此,在打开弹出窗口时,连接似乎很慢或暂时很慢,导致其阻塞,至少在我的测试环境中是这样。

我在没有附加组件的情况下运行 IE 进行了另一次测试, iexplore.exe -extoff, ,但最终得到相同的结果。我还修复了每次 iframe 的 URL 更改时都会重新创建页面上的 iframe 的问题。我的部分逻辑被省略了。现在 iframe 只创建一次。之后只有 src 当我想加载新内容时属性会更新...我的傻瓜。我注意到 JavaScript 闭包中存在一些挥之不去的窗口引用,因此现在当我完成它们时,它们在闭包中显式设置为 null。

我还做了一些内存泄漏调查:- 据我所知,我在 DOM 和 JavaScript 或这里提到的其他泄漏模式中没有任何循环引用, http://www.ibm.com/developerworks/web/library/wa-memleak/?S_TACT=105AGX52&S_CMP=cn-a-wa

  • 我添加了 Crokenator 的 IE 内存泄漏清除代码(请参阅 http://www.crockford.com/javascript/memory/leak.html):

    $(document)。

        if (a) {
            l = a.length;
    
            for (i = 0; i < l; i += 1) {
                if (a[i]) {
                    n = a[i].name;
    
                    if (typeof d[n] === 'function') {
                        d[n] = null;
                        purgeCount++;
                    }
                }
            }
        }
    
        a = d.childNodes;
    
        if (a) {
            l = a.length;
            for (i = 0; i < l; i += 1) {
                purge(d.childNodes[i]);
            }
        }        
    }        
    
    $(window).unload(function() {
      purge(document.body);
      //alert("purge count: " + purgeCount);
    });
    

    });

我的所有改进都没有解决问题。在我本地的测试场景中。有任何想法吗?任何人?任何人?布勒?

最后更新

感谢 David 指出是会话状态导致了 Web 服务中的问题。 “ASP.NET 将所有请求排队到同一“会话”。因此,如果第一个请求阻塞时间过长,它将阻止任何其他排队的请求。”

因此,我们最终所做的就是尝试使用会话状态最小化 Web 服务,但我们还添加了 Microsoft 推荐的连接数设置,请参阅 http://msdn.microsoft.com/en-us/library/ff647786.aspx#scalenetchapt10_topic9

有帮助吗?

解决方案

我认为您可能遇到会话请求同步问题。您是否已将 Web 服务处理程序标记为需要会话状态?

ASP.NET 将所有请求排队到同一个“会话”。因此,如果第一个请求阻塞时间过长,它将阻止任何其他排队的请求。您可以关闭页面的会话状态以避免这种情况并实现真正的异步,但是您将无法访问服务器上的会话等。

如果您使用 .ashx,则必须使用接口来访问会话状态,默认为关闭,因此请检查您是否添加了这些接口之一,并在可能的情况下删除:

public class FooHandler : IHttpHandler, IReadOnlySessionState // readonly access

public class FooHandler : IHttpHandler, IRequiresSessionState // read-write access

如果您使用的是 aspx 页面,则默认情况下它是打开的,您必须使用 Page 指令属性将其关闭:

    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs"
AutoEventWireup="false" Inherits="WebApplication1.WebForm1"
EnableSessionState="false" %>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top