2011-06-28 15 views
7

Mój silnik graficzny aplikacji zgłasza te wyjątki. Wszystkie są pochłaniane przez pusty blok catch. We wczesnych dniach znalazłem taki, który nie był uwięziony (jak pamiętam, związany z poszerzaniem pióra). Otoczyłem go try i pusty blok catch. Wydaje się, że te wyjątki nie mają wpływu na powstały rysunek. Zrobiłem trochę czytania na ten temat bez naprawdę zrozumienia lub dotarcia do sedna.System.Drawing z wyjątku pamięci

Więc na moje pytania:

  1. Dlaczego one zostać wyrzucony, jeśli mogą one być spożywane bezpiecznie? i
  2. Czy można je zignorować? Obawiam się, że każdy ma jakiś ukryty efekt. Mam wycieki pamięci, których nigdy nie znalazłem na przykład.
+0

Pozbywasz się takich rzeczy jak Długopisy, Pędzle, Grafika, Obrazy po użyciu? –

+4

Zostaną rzucone, aby powiedzieć, że twój kod jest uszkodzony. Złapanie ich za pomocą pustej klauzuli catch nie naprawia twojego kodu, po prostu wystrzeliwuje posłańca. –

+1

GDI + czasami zgłasza wyjątek braku pamięci, gdy w rzeczywistości jest to nieprawidłowy argument. Nie jestem pewien, czy ma to znaczenie tutaj. – CodesInChaos

Odpowiedz

19

Widziałem System.Drawing rzucić OutOfMemoryExceptions, nawet jeśli nie ma go w pamięci. Niektóre funkcje GDI + najwyraźniej właśnie zwracają głupi kod błędu.

IIRC, otrzymasz OutOfMemoryException, jeśli spróbujesz użyć LinearGradientBrush do wypełnienia prostokąta, którego szerokość lub wysokość wynosi zero. Mogą również istnieć inne warunki, ale to jest główny problem, na który natrafiliśmy.

W takim przypadku nie ma potrzeby próby/catch. Wystarczy dodać instrukcję if do kodu rysunku i nie wypełniać prostokąta, jeśli szerokość lub wysokość wynosi zero.

Aktualizacja: Według komentarzy na this answer, może również wystąpić, jeśli spróbujesz załadować uszkodzony plik obrazu. W tym celu nie miałbyś innego wyboru, jak tylko spróbować/złapać.

Prawdopodobnie bezpiecznie wychwytywacie OutOfMemoryExceptions z GDI +, ale starajcie się, aby bloki try były jak najmniejsze.Rozważ rejestrowanie wyjątków, aby móc analizować dzienniki i dodawać kod defensywny tam, gdzie to możliwe. Nie chcesz maskować prawdziwego OutOfMemoryException, ale nie chcesz, aby głupi kod błędu GDI + spowodował awarię aplikacji.

+0

Nie ma pliku obrazu, który jest zaangażowany w rysowanie. Świetny pomysł, aby korzystać z rejestrowania. Aplikacja ma rejestrator, więc dodam trochę logowania do klauzul catch i zobaczę, co się pojawi. Jeśli wygląda paskudnie, dodam kod obronny. – ScruffyDuck

+0

Dziękujemy od 2016! Uratowałeś mój dzień! – Genius

+0

Co zrobić, jeśli musisz narysować linię gradientu, która jest pionowa lub horyzontalna? Wtedy prostokąt miałby zerową szerokość lub wysokość! – AaronF

2

Jest to bardzo złe wyjątek: http://msdn.microsoft.com/en-us/library/system.outofmemoryexception.aspx .. mało pamięci, aby kontynuować wykonywanie programu.

Często zdarza się, że przy tak dużej alokacji, że "proste" operacje/przydziały wyrzucają tę wiadomość, aplikacja wkrótce ulegnie awarii. Jeśli to jedna ogromna alokacja, która się nie powiedzie, możesz kontynuować.

Jeśli aplikacja robi coś ważnego, powinieneś spróbować z wdziękiem zamknąć wszystko.

Aby jednoznacznie odpowiedzieć na Twoje pytania:

  1. Oni wyrzucony więc aplikacja ma szansę na reakcję/odzyskania: niektóre przydziały pamięci (10GB wartości obiektów) można spodziewać się niepowodzeniem w wielu sytuacjach, być może jedna linia aplikacja zderzeniowych (int[] x = new int[5368709120]; odpowiednik) powinien naprawdę wyjątek zamiast upaść wszystkiemu

  2. nie powinno być ukryty efekt, ale jeśli przydział nie powiedzie, to może następnym razem chcesz string lub inne użyteczne obiekt w jakiś niewielki sposób przeznaczony do ogólnego działania aplikacji: rzeczy mogą stać się niestabilne. Powiedział, że w zależności od środowiska, można uzyskać ten wyjątek w każdej chwili ..

Edycja: Każdy czyta ten powinien również rozważyć, że widocznie GDI + zgłasza to wyjątek dla innych powodów też.

+0

Dzięki - szczerze powiedziawszy, nigdy nie doszło do wniosku. Mamy około 30 000 użytkowników i nie zostało to zgłoszone. Jednak jeśli przyjrzę się dziennikowi wyników w VS, widzę kilkadziesiąt "wyjątków pierwszej szansy" tego typu, które są zużywane przez pustą klauzulę (-y) catch – ScruffyDuck

+2

OOM oznacza coś innego, gdy GDI + wyrzuca to. Wyjątki GDI + są dość niechlujne. –

+0

Zwykle to prawda, ale GDI + rzuca OutOfMemoryExceptions, nawet jeśli nie ma w nim pamięci. Widziałem to. Niektóre funkcje zwracają błędny kod błędu lub coś podobnego. –

0

Wypróbowałem rozwiązanie "Joe White" zasugerowane i to było to. Wyrzucono wyjątek OutOfMemoryException, ponieważ szerokość i wysokość prostokąta wyniosły 0. W moim przypadku okno zostało zminimalizowane, gdy wystąpił wyjątek.

Oto przykład;

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) 

    Using e 
     ##Add conditions to avoid OutOfMemoryException## 
     If (Not ClientRectangle.Width = 0) And (Not ClientRectangle.Height = 0) Then 
      Using rect As GraphicsPath = New GraphicsPath() 
       rect.AddRectangle(ClientRectangle) 

       Using gb As New PathGradientBrush(rect) 
        gb.WrapMode = WrapMode.Tile 
        gb.SurroundColors = New Color() {GradientColors(1), GradientColors(0), GradientColors(2)} 
        gb.CenterColor = GradientColors(0) 
        gb.SetSigmaBellShape(0.5F) 
        e.Graphics.FillPath(gb, rect) 
       End Using 
      End Using 
     End If 
    End Using 

End Sub 
Powiązane problemy