Foreach загадочно висит на первом элементе ResourceSet
Иногда наш сайт замедляется, а использование ОЗУ растет очень высоко. Затем пул приложений останавливается, и я должен перезапустить его. Затем это нормально в течение нескольких дней, прежде чем ОЗУ внезапно всплескается снова, и вскоре пул приложений прекратится. CPU невелик.
До остановки приложения я заметил, что один из наших страниц всегда зависает. Линия, на которой он висит, является foreach в ResourceSet:
var englishLocations = Lang.Countries.ResourceManager.GetResourceSet(new CultureInfo("en-GB"),true,true);
foreach(DictionaryEntry entry2 in englishLocations) // THIS LINE HANGS
У нас есть тот же код, который разворачивается в другом поле, и этого не происходит. Основные отличия между двумя полями:
Плохая коробка
- Window Server 2008 R2 Standard SP 1
- IIS 7.5.7600.16385
- .NET 4.5
- ОЗУ 24 ГБ
Хорошая коробка
- Окно Server 2008 Server SP 2
- IIS 7.0.6000.16386 SP 2
- .NET 4.0
- ОЗУ 24 ГБ
Я попытался добавить uploadReadAheadSize = "0" в web.config, как описано здесь:
http://rionscode.wordpress.com/2013/03/11/resolving-controller-blocking-within-net-4-5-and-asp-net-mvc/
Что не сработало.
Почему бы не повесить? Он висит на самом первом предмете, фактически на foreach.
Спасибо.
Ответы
Ответ 1
Я знаю, что это старый пост, но тем не менее... Существует потенциал тупика при повторении через ResourceSet и в то же время извлечение другого объекта из одних и тех же ресурсов.
Проблема заключается в том, что при использовании ResourceSet итератор извлекает блокировки во внутреннем кэше ресурсов ResourceReader http://referencesource.microsoft.com/#mscorlib/system/resources/resourcereader.cs,1389, а затем в методе AllocateStringNameForIndex вынимает блокировка самого читателя: http://referencesource.microsoft.com/#mscorlib/system/resources/resourcereader.cs,447
lock (_reader._resCache) {
key = _reader.AllocateStringForNameIndex(_currentName, out _dataPosition); // locks the reader
Получение объекта выдает те же блокировки в противоположном порядке:
http://referencesource.microsoft.com/#mscorlib/system/resources/runtimeresourceset.cs,300
и http://referencesource.microsoft.com/#mscorlib/system/resources/runtimeresourceset.cs,335
lock(Reader) {
....
lock(_resCache) {
_resCache[key] = resLocation;
}
}
Это может привести к тупиковой ситуации. Недавно у нас была эта точная проблема.
Ответ 2
У меня возникла очень схожая проблема.
Время от времени IIS зависает, и я вижу, что количество запросов просто сидит там. Все они были в состоянии ExecuteRequestHandler
и с именем модуля ManagedPipelineHandler
.
После исследования с помощью проводника процессов я увидел, что все они сидели в mscorlib.dll!ResourceEnumerator.get_Entry
, дополнительная трассировка стека предложила какое-то действие NGen, а затем ntdll.dll!WaitForMultipleObjects
.
Моя рабочая гипотеза заключается в том, что, когда несколько потоков начинают перечислять эти ресурсы, мы можем зайти в тупик (возможно, при генерации некоторого встроенного кода), а все последующие потоки все же продолжают накапливаться.
Чтобы решить эту проблему, я просто создал критический раздел вокруг этого блока кода, чтобы убедиться, что он выполняется последовательно - с тех пор я не сталкивался с этой проблемой.
private static readonly object ResourceLock = new object();
public static MvcHtmlString SerializeGlobalResources(this HtmlHelper helper)
{
lock (ResourceLock)
{
// Existing code goes here ....
}
}
Ответ 3
Основываясь на другом ответе, чтобы дать вам некоторое представление о том, как использовать модель try catch?
Возможно, он зависает, потому что этот ресурс недоступен/заблокирован/..перечисления и т.д.
var englishLocations = Lang.Countries.ResourceManager.GetResourceSet(new CultureInfo("en-GB"),true,true);
foreach(DictionaryEntry entry2 in englishLocations) // THIS LINE HANGS
ResourceManager CultureResourceManager = new ResourceManager("My.Language.Assembly", System.Reflection.Assembly.GetExecutingAssembly());
ResourceSet resourceSet = CultureResourceManager.GetResourceSet("sv-SE", true, true);
try { resourceSet.GetString("my_language_resource");}
catch (exception ex) { // from here log your error ex to wherever you like with some code }