2013-06-09 2 views
3

У меня есть метод, который должен обрабатывать предоставленный пользователем файл, и если файл достаточно сложный, я могу столкнуться с OutOfMemoryException. В этих случаях я отлично справляюсь с тем, что метод не работает, но я хочу, чтобы приложение оставалось пригодным для использования, проблема в том, что после получения OutOfMemoryException я ничего не могу сделать, так как каждый ход действия потребляет память.Восстановление из OutOfMemoryException

Я думал о том, чтобы отложить в сторону некоторую память, которую я могу освободить после того, как исключение будет выбрано, чтобы остальная часть приложения могла продолжить, но похоже, что оптимизатор избавляется от этого распределения.

public void DoStuff(string param) 
{ 
    try 
    { 
#pragma warning disable 219 
     var waste = new byte[1024 * 1024 * 100]; // set aside 100 MB 
#pragma warning restore 219 

     DoStuffImpl(param); 
    } 
    catch (OutOfMemoryException) 
    { 
     GC.Collect(); // Now `waste` is collectable, prompt the GC to collect it 
     throw; // re-throw OOM for treatment further up 
    } 
} 

Короче мои вопросы:

  1. Есть ли лучший способ сделать то, что я пытаюсь?
  2. Если нет, есть ли веская причина, почему это плохая идея?
  3. Предполагая, что эта идея - путь, как заставить JIT не оптимизировать мою память waste?
+0

Сделайте свою программу 64-битной и добавьте эту строку в свой файл app.config: http://msdn.microsoft.com/en-us/library/hh285054(v=vs.110).aspx –

+0

Или, альтернативно, проверьте файл размер. –

+0

@newStackExchangeInstance Я не хочу устанавливать произвольные ограничения на размер файла, и в любом случае объем потребляемой памяти строго не коррелирует с размером файла. Что касается 64-битного, это в настоящее время не вариант, так как многие другие части приложения являются C++, и поэтому переход на 64 бит имеет много последствий. – Motti

ответ

1

Я бы не реконструировал исключение OOM, если память уже очищена.

В противном случае внешний код не будет знать этого и будет думать, что ему нужно освободить еще немного памяти, тогда как на самом деле этого не нужно.

Так что я бы выбрал для исключения пользовательских исключений.

1

Если это поставляется пользователем файл, вы можете проверить размер файла перед обработкой его:

FileInfo f = new FileInfo(fileName); 
long s1 = f.Length; 

Это SO нить объясняет пределы памяти для .NET приложения в 32-разрядной. Allocating more than 1,000 MB of memory in 32-bit .NET process

Зная размер файла и объем памяти, приложение уже потребляющим может быть чек, если вам необходимо очистить все ресурсы, прежде чем пытаться обрабатывать, или, если вы будете в состоянии обработать на все ,

+0

Спасибо, но сложность файла не обязательно коррелирует с его размером. – Motti

+0

Не могли бы вы уточнить? Вы заставляете это звучать, как 100 МБ-файл, может быть настолько сложным, что приложение будет потреблять X раз больше размера файла. – Shar1er80

+0

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