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 }