2012-04-03 4 views
0

В это время приложение потребляло около 150 МБ памяти. Посмотрите на это:Ошибка использования памяти при использовании приложения?

Исключение messsage:

Исключение типа 'System.OutOfMemoryException' был брошен.

Стек след: на System.Diagnostics.NtProcessInfoHelper.GetProcessInfos() в System.Diagnostics.ProcessManager.GetProcessInfos (String MACHINENAME) в System.Diagnostics.Process.EnsureState (государственный штат) в System.Diagnostics. Process.get_WorkingSet64() в StreamSink.frmMain.get_MemoryUsed() в C: \ Projects \ VideoPhill \ PlayerRAC \ StreamSink \ StreamSink \ StreamSink \ frmMain.cs: строка 819 в StreamSink.frmMain.CalculateStatistics() в C: \ Projects \ VideoPhill \ PlayerRAC \ StreamSink \ StreamSink \ StreamSink \ frmMain.cs: строка 803 в StreamSink.frmMain._timerUI_Tick (отправитель объекта, EventArgs e) в C: \ Projects \ VideoPhill \ PlayerRAC \ StreamSink \ StreamSink \ StreamSink \ frm Main.cs: линия 736 в System.Windows.Forms.Timer.OnTick (EventArgs е) в System.Windows.Forms.Timer.TimerNativeWindow.WndProc (Сообщение & м)

Ну, что случилось Вот?

РЕД (подробнее):

Это один терпит неудачу:

private long MemoryUsed 
    { 
     get 
     { 
      return Process.GetCurrentProcess().WorkingSet64/1024/1024; 
     } 
    } 

И вызывается из:

private void CalculateStatistics() 
    { 
     if (InvokeRequired) 
     { 
      this.BeginInvoke(new MethodInvoker(CalculateStatistics)); 
     } 
     else 
     { 
      barStaticItem1.Caption = "Mem: " + MemoryUsed.ToString() + " MB"; 
     } 
    } 

, который вызывается из события таймера и таймера типа: System.Windows.Forms.Timer.

* Ошибка НЕ ​​МОЖЕТ быть воспроизведена сама по себе. *

+0

(Перемещение этого комментария к вопросу, поскольку я удаляю свой ответ на данный момент): Хм, это выглядит немного странно. Я все еще подозреваю, что таймер может иметь к этому какое-то отношение. Что произойдет, если вы измените его, чтобы вызов не запускался таймером? –

+0

@BrianRasmussen не пробовал, так как это происходит каждые две недели и только в производстве. Нет никаких шансов спровоцировать это ... –

+0

@ DanielMošmondor: Не могли бы вы отправить полный код для воспроизведения (à la http://www.yoda.arachsys.com/csharp/complete.html)? –

ответ

1

Я пойду на конечность здесь и заметлю, что есть что-то подозрительное в отношении сделанных предположений. Во-первых, зачем вы пишете такой код? На самом деле это общий для приложения для работы из памяти и это, почему вы хотите отображать использование памяти в пользовательском интерфейсе? Во-вторых, как вы уверены, что приложение фактически использует только 150 МБ, если это происходит в процессе производства, но не на вашей dev-машине?

Я полагаю, что исключение является реальным, и предположения плохие. У процесса на самом деле закончилась нехватка памяти. То, что это произошло внутри кода, предназначенного для предупреждения пользователя о низком состоянии памяти, очень иронично. Но, конечно, не невозможно, функция родной ОС, которая поставляет информацию, нуждается в довольно большом буфере, когда на машине работает много процессов. Вместо этого вы должны были использовать свойство Environment.WorkingSet.

Также весьма примечательно то, что получение 150 МБ из WorkSet и получение OOM вполне возможно. Это Неверный Статистика. WorkSet описывает, сколько оперативной памяти вы используете. Но OOM запускается, когда у вас заканчивается виртуальная память. Две очень разные меры. Рабочий набор невелик, когда страницы виртуальной памяти поменяются на файл подкачки. Скорее всего, это произойдет, когда много процессов запущено, конкурируя за ОЗУ.

Для измерения размера виртуальной машины нет доступной собственности. В основном потому, что это в значительной степени бесполезно, размер отверстий на карте памяти является тем, что важно. Вы получаете OOM, когда нет дыры, достаточно большой, чтобы соответствовать распределению. Если вы хотите отобразить полезную статистику, то GC.GetTotalMemory() несколько полезен. Только несколько, он не учитывает неуправляемую память. Решите все свои проблемы, указав в своих требованиях 64-разрядную операционную систему.

+0

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

0

Ваш код действительно не показывает, если BeginInvoke должен что-то делать здесь (поскольку мы не знаем, когда InvokeRequired истинно).

Так, очевидно, этот код может быть не удается, так как все другие код выглядит нормально:

Process.GetCurrentProcess().WorkingSet64/1024/1024; 

Я предлагаю вам сделать небольшое приложение, которое стресс-тесты Process.GetCurrentProcess() WorkingSet.. Но, чтобы быть правдой, я сомневаюсь, что это поможет (если у вашей производственной машины не будет аппаратных проблем).

Я вижу, вы используете barStaticItem1 - должен быть контроль, не так ли? Ну, если вы запускаете разные потоки, и этот элемент управления не является потокобезопасным или не должен использоваться из другого потока (отличного от потока, который создал этот элемент управления), это может быть источником вашей проблемы: 1. встречается редко ; 2. вы не можете сделать это, когда захотите.

+0

Мы знаем, что InvokeRequired не является истинным, так как у нас есть стек вызовов выше, и если бы это было так, это не выглядело бы так ... –

+0

Затем удалите эту часть кода из вашего примера. – Dima

+0

Не будет, так как вставка кода и весь вопрос погружаются глубже и глубже в бессмысленность :) –

1

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

Если вы не можете придумать какую-либо причину, по которой приложение должно использовать столько памяти, скорее всего, у вас может быть утечка памяти. Возможно, вам стоит подумать о захвате профилировщика памяти, например, ANTS Memory Profiler, чтобы проверить, действительно ли это так, и если да, то где он лежит.

0

Я думаю, что причина недостаток был код был выполнен в несколько раз фоновых потоков, и не было никаких покидающие условий на рекурсивном вызове this.BeginInvoke(new MethodInvoker(CalculateStatistics));

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

private void CalculateStatistics() 
    { 

     Action showMemoryUsage =() => 
            { 
             barStaticItem1.Caption = "Mem: " + MemoryUsed.ToString() + " MB"; 
            }; 
     if (InvokeRequired) 
     { 
      this.BeginInvoke(new MethodInvoker(showMemoryUsage)); 
     } 
     else 
     { 
      showMemoryUsage(); 
     } 
    } 
Смежные вопросы