2012-08-16 34 views
5

Tworzę Label, a czasami używam .DrawToBitmap(). Nie wiem dlaczego, ale po Im działa mój program na chwilę (i wywołanie .DrawToBitmap() częściej) pojawia się wyjątek:DrawToBitmap - System.ArgumentException: Parametr jest nieprawidłowy

System.ArgumentException: Parameter is not valid. 
    at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format) 
    at System.Drawing.Bitmap..ctor(Int32 width, Int32 height) 

Jakoś nie może wywołać tę funkcję, które często. Jeśli bym radykalnie spróbował tego:

while(true) 
{ 

    System.Windows.Forms.Label label = new Label(); 

    label.Font = new Font("Arial", 20); 
    label.Text = "test"; 

    try 
    { 
    Bitmap image = new Bitmap(300, 500); 
    label.DrawToBitmap(image, label.ClientRectangle); 
    } 
    catch (Exception e) 
    { 
    Console.WriteLine(e); 
    } 
} 

Dostałem po 5-6 sekundach (1000-2000 połączeń) wyjątek. Jaki jest problem? Jak tego uniknąć?

Edytowanie: Dziękujemy za pomysł z Dispose() - jakoś wszystko działa idealnie, jeśli używam go na label. Nawet jeśli nie używam go w Bitmapie, to jest w porządku. Obie odpowiedzi są świetne, mogę jedynie przyjąć 1 z nich :(

Odpowiedz

6

Tak, że komunikat o błędzie pochodzi z głęboko w GDI + i mogą pojawić się na a lot powodów. Widzę jeden rażące problem z kodem że jest kandydatem jednakże:..

label.Font = new Font("Arial", 20); 

Font obiekty wdrożyć IDisposable i tworzysz wiele z nich w ciasnej pętli i nigdy nie dzwoni Dispose() samo dotyczy samego Bitmap Chciałbym założyć, że GDI jest na wyczerpaniu zasobów:

To har d, aby zrozumieć kod w jego obecnym stanie. Zasadniczo nie robi absolutnie nic, ale tworzy mnóstwo obiektów Font i Bitmap, więc nie mogę nawet zasugerować zawijania każdej z tych deklaracji w oświadczeniu using. Poza tym, gdy tworzysz masę obiektów GDI w krótkim odstępie czasu bez ich pozbycia się, w końcu napotkasz ten problem.

Jeśli potrzebujesz tych obiektów, aby były ważne przez pewien czas, musisz upewnić się, że zadzwonisz na nie później, aby wydobyć natywne zasoby w jak najkrótszym czasie (finalizator zrobi to za Ciebie, ale najlepiej nie czekać na to). Jeśli są lokalne obiekty następnie zawinąć je w using oświadczeniu tak Dispose() zostanie wywołana po wyjściu bloku:

using(var b = new Bitmap(w, h)) 
{ 
    // use 'b' for whatever 
} // b.Dispose() is called for you 
+0

cześć. Na początku próbowałem używać (Bitmap ...) => żadnych zmian. Ale kiedy używałem label.Dispose() na końcu każdego połączenia wszystko było w porządku :) Dziękuję - przetestowałeś to z 30.000 połączeń, myślę, że to w porządku teraz. Bez etykiety.Dispose() Otrzymuję wyjątek po 1000-2000 wywołań. Nigdy nie myślałem, że muszę się pozbyć() etykiety. – miri

+0

@miri: Jak @HansPassant: Wydaje mi się, że wyrzucenie etykiety spowodowałoby wyjątek. Wierzę, że jest to czcionka i bitmapa, które powinny być zawijane w bloki 'używając'. Nie wiem, w jaki sposób można uciec z wyrzuceniem etykiety, nie widząc, w jaki sposób etykieta jest używana inaczej. – IAbstract

4

GDI + wyjątkami są dość słabe, często nie opisują rzeczywisty problem dobrze. W tym przypadku oznacza to, że "bitmapa jest zbyt duża". Które wciąż nie opisują tego dobrze, w rzeczywistości kończy ci się niezarządzana pamięć. Mapa bitowa jest zbyt duża, aby zmieścić ilość dostępnej pamięci.

Ponieważ nie wywołuje metody Dispose() na mapie bitowej. Często możesz skąpić, nie zauważając kłopotów. Ale nie w przypadku Bitmapy, jest to klasa, która zajmuje bardzo mało zebranej pamięci, ale dużo niezarządzanej pamięci. Nie uruchamia on garbage collector wystarczająco szybko, aby umożliwić finalizatorowi zwolnienie pamięci niezarządzanej.

Fragment kodu nie ma sensu, ale trzeba napisać to tak, aby uniknąć wyjątek:

using (Bitmap image = new Bitmap(300, 500)) { 
    label.DrawToBitmap(image, label.ClientRectangle); 
} 
+1

Poważnie, * poważnie * nienawidzę komunikatów o błędach GDI ... wymaga to tylko diagnozy problemu, co powoduje, że sama wiadomość jest bezużyteczna. –

+0

Dziękuję za pomysł! Dispose() jest świetny, ale jakoś muszę go użyć na etykiecie. – miri

+0

Cóż, nie, na pewno nie chcesz pozbyć się etykiety, która sprawi, że zniknie i zawiesi twój kod. Usuń bitmapę. –

Powiązane problemy