2014-09-30 2 views
0

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

private void ReturnTexture(Texture texture_take, List<Point> lstPnt, float[] anglArr, float angle) 
     { 
      int i, j, bytes = 2048 * 512, stride = 2048; 
      GraphicsStream textureStream; 
      byte[] rgbValues = new byte[bytes]; 

      //sets texture to complete transparent 
      GCHandle gch = GCHandle.Alloc(rgbValues, GCHandleType.Pinned); 
      MemSet(gch.AddrOfPinnedObject(), 0x0, rgbValues.Length); 

      //add 90 degrees because the cone starts at 90 
      angle += 90F + 23.75F; 

      //checks all points and draws yellow only those how are inside the cone 
      if (lstPnt != null) 
      { 
       for (i = 0; i < lstPnt.Count - 1; i++) 
       { 
        if (anglArr[i] <= angle && anglArr[i] >= angle - 47.5F) //if point angle is inside cone. Cone angle is 47.5 degrees 
        { 
         j = lstPnt[i].Y * stride + lstPnt[i].X * 4; 

         //yellow 
         rgbValues[j + 0] = (byte)0; 
         rgbValues[j + 1] = (byte)255; 
         rgbValues[j + 2] = (byte)255; 
         rgbValues[j + 3] = (byte)255; 
        } 
        else 
        { 

        } 
       } 
      } 

Исключение находится на линии:

byte[] rgbValues = new byte[bytes]; 

Когда исключение произойдет, я вижу, что переменные байты содержат: 1048576 И rgbValues ​​является нулевым

Я использовал контрольную точку перед исключением произошел и увидел, что значение в байтах было одинаковым: 1048576, но исключение происходит только через 20 секунд или около того, а не только в начале.

Необработанное исключение типа 'System.OutOfMemoryException' произошло в Weather Radar.exe

System.OutOfMemoryException was unhandled 
    HResult=-2147024882 
    Message=Exception of type 'System.OutOfMemoryException' was thrown. 
    Source=Weather Radar 
    StackTrace: 
     at Weather_Radar.Form1.ReturnTexture(Texture texture_take, List`1 lstPnt, Single[] anglArr, Single angle) in d:\C-Sharp\Weather Radar\Weather Radar\Weather Radar\Form1.cs:line 314 
     at Weather_Radar.Form1.timer1_Tick(Object sender, EventArgs e) in d:\C-Sharp\Weather Radar\Weather Radar\Weather Radar\Form1.cs:line 59 
     at System.Windows.Forms.Timer.OnTick(EventArgs e) 
     at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m) 
     at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
     at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
     at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.Run(Form mainForm) 
     at Weather_Radar.Program.Main() in d:\C-Sharp\Weather Radar\Weather Radar\Weather Radar\Program.cs:line 19 
     at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
     at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
    InnerException: 

Линия 314 в Form1 является: байт [] rgbValues ​​= новый байт [байт];

Строка 59 в форме1 есть: ReturnTexture (scannedCloudsTexture, cloudPoints, angleArray, angleF);

Это таймер код клещ событие:

static float angle_ = 0.0F; 
     static float angleF = 0.0F; 
     private void timer1_Tick(object sender, EventArgs e) 
     { 
      if (angleF > 360F) 
      { 
       angleF -= 360F; 
      } 

      ReturnTexture(scannedCloudsTexture, cloudPoints, angleArray, angleF); 

      DisplayOnScreen(angle_); 

      angle_ += (float)(Math.PI * 1d/180d); 
      angleF += 1.0F; 
     } 
+1

GCHandle защищен от сборщика мусора, поэтому вы должны освободить использование памяти, вызвав метод GCHandle.Free, когда ручка больше не нужна – InferOn

+1

Держу пари, каждый таймер гасит вашу оперативную память. Попробуйте повторно использовать массив и не создавать на каждом тике – Reniuz

ответ

1

Как пояснил в комментарии по Renuiz, похоже, вы не освобождая память, выделенную для вашего изображения. Когда вы позвоните: GCHandle.Alloc

Новый GCHandle, который защищает объект от сбора мусора. Этот GCHandle должен быть выпущен Free, если он больше не нужен.

Если вы не FreeGCHandle, 1 МБ выделено код никогда не будет освобожден. Я думаю, что существует два возможных варианта:

  • Повторно используйте byte[], если возможно, не требуя больше памяти. Держите GCHandle, чтобы вы могли их свести к нулю для каждого тика.
  • Не вставляйте byte[] в память, используя GCHandle. Когда вы создаете новый byte[]all values will be set to zero в любом случае.
Смежные вопросы