Вызов веб-службы в JavaScript приводит к появлению белого экрана смерти (WSOD) в браузере
Вот технические характеристики:
- ASP.NET 3.5 с использованием ASP.NET AJAX
- AJAX Control Toolkit
- JQuery 1.3.2
- веб-сервисы
- IIS6 на Windows Server 2003 с пакетом обновления 1
- SP1 SQLServer 2005 SP3 Сайт является SSL
- Infragistics Web Components 2009 Vol. 2 (с использованием элементов управления, отличных от айкидо), UltraWebGrid и Tree используются в основном.
Вот проблема: я получаю Белый Экран Смерти (WSOD) в IE 7/8. По сути, у меня есть страница с левой панелью, в которой есть элемент управления аккордеоном AJAXControl Toolkit, где каждый контент панели аккордеона представляет собой элемент управления дерева инфраструктуры. Правая панель <div>
это имеет <iframe>
чей контент перезагружается в зависимости от того, что щелкнуло в левой панели меню.
в <iframe>
, страница с одним или несколькими элементами управления UltraWebGrid загружается при нажатии на элемент меню в левой панели. Все сетки имеют шаблонный столбец кнопок. При нажатии на кнопку редактирования строки сетки открывается всплывающее окно для редактирования записи. Это работает нормально около десяти раз, а затем в десятый раз (иногда раньше) открывается всплывающее окно с правильным URL-адресом в адресной строке, но страница никогда не загружается.
У нас есть приложение, которое использует одно всплывающее окно для обновления записей. В большинстве случаев, когда вы нажимаете кнопку [Редактировать] для редактирования записи, открывается всплывающее окно и загружается страница обновления. Однако, после некоторого редактирования записей, внезапно открывается всплывающее окно, но оно остается пустым и просто зависает. URL находится в адресной строке.
Загрузка Fiddler Я заметил, что запрос на страницу обновления никогда не отправляется, что наводит меня на мысль, что это какая-то блокировка на стороне клиента. Если я скопирую тот же URL, что и во всплывающем окне, в новое окно браузера, страница обычно загружается нормально.
Наблюдения: - Поскольку запрос никогда не отправляется на сервер, он определенно связан с клиентом или браузером. - Похоже, что это происходит только тогда, когда на сайте есть некоторое подобие трафика, что странно, потому что кажется, что оно содержится в коде на стороне клиента. - Каждые несколько секунд в фоновом режиме вызывается веб-служба, проверяющая, вошел ли пользователь в систему., но это не вызывает замораживание.
Я действительно в растерянности здесь. Я погуглил WSOD, но, похоже, не так уж много связано с моим конкретным WSOD. Есть идеи?
В чем проблема на самом деле
Оказывается, утечки памяти (хотя некоторые из них были закрыты на стороне клиента) не являются проблемой. Проблема заключается в том, что вызовы веб-службы выполняются на стороне клиента. Есть один, который проверяет, вошел ли пользователь в систему каждые 4 секунды (для синхронизации с другим окном), а затем выполняются вызовы веб-службы для получения пользовательских настроек для всплывающего окна и состояния сетки. Из того, что я прочитал, веб-сервисы должны быть асинхронными. Я предположил, вызывая их из JavaScript с обратными вызовами "успех / неудача", что они были асинхронными, но на самом деле это не так. Они асинхронны с точки зрения клиента / браузера, но со стороны сервера выполняется вызов веб-службы, который возвращается после завершения всех других операций, поскольку число подключений ограничено.
Так какой же самый простой способ сделать методы веб-службы асинхронными? Нужно ли преобразовывать веб-службу в веб-службу WCF или можно использовать существующий вызов веб-службы ASP.NET?
И для исторических целей вот то, что я думал, что проблема была первоначально:
Я не смог воспроизвести это локально или на наших серверах тестирования. Тем не менее, я заставил Fiddler имитировать скорость модема, и внезапно я смог скопировать 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
Я добавил код очистки Crockenator для утечек памяти в IE (см. http://www.crockford.com/javascript/memory/leak.html):
$ (document).ready (function () {function purge (d) {var a = d.attributes, i, l, n;
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); });
});
Ни одно из моих улучшений не устранило проблему. в моем локальном тестовом сценарии. Есть идеи? Кто-нибудь? Кто-нибудь? Bueller?
Последнее обновление
Спасибо Дэвиду за то, что он указал, что именно состояние сеанса вызывает проблемы в веб-сервисах. "ASP.NET помещает все запросы в один и тот же" сеанс ". Поэтому, если первый запрос блокируется слишком долго, он задержит любые другие запросы в очереди".
В итоге мы постарались минимизировать количество веб-сервисов, используя состояние сеанса, но мы также добавили рекомендуемые настройки Microsoft для количества соединений, см. http://msdn.microsoft.com/en-us/library/ff647786.aspx
1 ответ
Я думаю, что у вас могут быть проблемы с синхронизацией запросов сеанса. Вы пометили обработчики веб-службы как требующие состояния сеанса?
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" %>