Странное поведение службы Windows на C #, когда используется более 90% ОЗУ - PullRequest
0 голосов
/ 04 октября 2011

Некоторое время я пытался отладить свой алгоритм, который синхронизирует данные между двумя базами данных. Все работало нормально в течение нескольких месяцев ежедневного использования, и в последнее время стали происходить странные вещи, например:

  • Свойству «DisableBuyButton» иногда присваивалось значение «истина», в то время как в файле конфигурации было явно задано значение «ложь» (я слишком много раз обходил алгоритм, чтобы найти что-то странное - ничего не нашел, и при этом все делал на моей машине было в порядке)
  • продукты были отнесены к категориям, отличным от ожидаемых

и много похожих ошибок.

Потом я вспомнил, что на одном собрании CodeCamp кто-то сказал, что при отладке приложений ASP.NET у них была проблема с сборщиком мусора, который находился в каком-то «режиме паники» - это вызвало много неожиданных и странных ошибок.

Я проверил, что происходит с объемом свободной памяти -> 90% было использовано. Я решил проблему, просто добавив 1 ГБ или ОЗУ к виртуальной машине - все эти странные вещи просто исчезли.

Теперь вопрос: КАК ЭТО ДАЖЕ ВОЗМОЖНО?

// edit: критический раздел, чтобы убедиться, что работает только один экземпляр:

        lock (this)
        {
            if (WorkStarted)
            {
                return;
            }
            else
            {
                WorkStarted = true;
            }
        }

1 Ответ

2 голосов
/ 04 октября 2011

Существует слишком много факторов, чтобы быть уверенными, но одна потенциальная проблема - это тихий откат к значениям по умолчанию (скажем, вы пытаетесь загрузить файл конфигурации каждый раз при обращении к свойству, но возвращаете значение по умолчанию, если не можете).

Еще одна проблема, с которой вы столкнулись, - это использование кеша.Вы можете иметь условия гонки или тайм-ауты, которые сбрасывают определенные значения в ноль, что в сочетании с вышеупомянутым может создать интересные ситуации.Это, вероятно, происходит только в тех случаях, когда не было доступа в течение достаточно длительного времени (что обычно приводит к перезагрузке процесса и повторному запуску при следующем доступе) или при работе с ситуациями с большим объемом памяти.

В основном сборщик мусоране собирается перебрасывать на вас биты случайным образом (или удалять доступный объект), но может делать вещи, которые могут появиться как таковые после слоев абстракции, которые мы добавляем.

РЕДАКТИРОВАТЬ:

Извините за долгий ответ, тема очень сложная, и я пытаюсь дать общеприменимый совет.

Давайте рассмотрим простой пример кэша, который упорядочивает все с последним временем доступа и помещает самый старый20% путем подсчета в WeakReference объектов в случае запуска ГХ.Затем вы переходите, чтобы получить информацию из кэша, но, поскольку срок ее действия истек, вы проверяете, существует ли она.Это вызывает HasValue свойство WeakReference, которое возвращает true.Наконец, вы идете, чтобы прочитать объект, но прежде чем вы можете GC запускает и убивает объект.Кэш корректно возвращает null, но теперь у вашего проекта есть null, где он ожидал значения.Не бояться, что подпрограмма обработки исключений обнаружит ошибку и решит вернуть вместо нее значение по умолчанию (false в случае bool).

Все это в совокупности создает ситуацию, когда ваш код не 'Если вы понимаете, что оно имеет неправильное значение, эта проблема может продолжаться некоторое время, если вы не перезвоните некоторое время.Подобные ситуации могут возникать, если ваш кэш реагирует на вызов GC, удаляя данные, возможно, в середине «безопасного» раздела кода.

Лучшее решение подобных проблем - следовать рекомендациям по использованию вашего кэша.к письму, или если вы катите свое собственное, то убедитесь, что вы понимаете любые взаимодействия, которые вы используете, например, как WeakReference и GC работают, или странные проблемы с синхронизацией при подключении к процессу GC.

Например, использование HasValue из WeakReference не очень хорошая идея, если вы действительно хотите получить это значение.Вместо этого вы должны просто получить Value, который в худшем случае вернет null, и вместо этого проверить на null (или в этот момент вы можете позвонить HasValue, так как GC не будет вмешиваться, если у вас есть ссылкак заостренному предмету, но бессмысленно, когда проверка null сделает)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...