2012-08-16 129 views
5

Im創建Label,有時使用.DrawToBitmap()。我不知道爲什麼,但是我運行後我計劃了一段時間(和調用.DrawToBitmap()經常)我得到異常:DrawToBitmap - System.ArgumentException:參數無效

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) 

不知怎的,我無法調用此函數經常。如果我可以從根本上嘗試這個:

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); 
    } 
} 

我得到5-6秒後(1000-2000調用)的例外。問題是什麼?如何避免這種情況?

編輯:謝謝大家與Dispose()這個想法 - 不知何故,如果我在label上使用它,一切都很完美。即使我不使用它在位圖上的罰款。這兩個答案都很好,我只能接受其中一個:(我的

回答

6

所以,這個錯誤信息來自GDI +內部的深處,可能會出現很多的原因。我看到一個明顯的代碼問題即然候選人:。

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

Font對象實現IDisposable和你在一個緊密的循環創造了他們很多,從來沒有叫Dispose()也是一樣的位圖本身我敢打賭,GDI用完的資源

它是har d來理解你的代碼。它基本上完全沒有什麼,但創建了大量的FontBitmap對象,所以我甚至不能建議將這些聲明中的每一個都包含在using聲明中。除此之外,當你連續創建大量GDI對象而不處理它們時,你最終會遇到這個問題。

如果您需要這些對象有效一段時間,那麼您需要確保您稍後調用Dispose()以儘可能及時地釋放本地資源(終結器將爲您做到這一點,但它是最好的不要等待它)。如果它們是本地對象,然後將它們包裝在using語句,以便將Dispose()塊時退出被稱爲:

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

嗨。起初,我嘗試使用(位圖...)=>沒有任何改變。但是當我在每次調用結束時使用label.Dispose()時,一切都很好:)謝謝 - 用30.000次調用測試它,現在我認爲這很好。沒有label.Dispose()我在1000-2000次調用後得到異常。從來沒有想過我必須處置()標籤。 – miri 2012-08-16 22:48:01

+0

@miri:就像@HansPassant:我以爲處置標籤會導致異常。我相信這是應該用'使用'塊包裝的字體和位圖。我不知道如何在不看標籤的情況下處理標籤。 – IAbstract 2012-08-17 14:11:12

4

GDI +的例外是比較差的,他們往往沒有說明真正的問題很好。在這種情況下,它確實意味着「位圖太大」。它仍然不能很好地描述它,你實際上已經用完了非託管內存。位圖太大而不適合仍可用的內存量。

因爲您沒有在位圖上調用Dispose()方法。你可以經常吝嗇,而不會注意到麻煩。但與位圖不同,這是一個只需要很少的垃圾收集內存,但有很多非託管內存的類。它不會足夠快地觸發垃圾收集器,讓終結器釋放非託管內存。

的代碼片斷是沒有意義的,但你會寫這樣避免了異常:

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

我認真對待*嚴重*討厭GDI錯誤信息......它只需要經驗來診斷問題,這使得信息本身無用。 – 2012-08-16 22:40:20

+0

謝謝你的想法! Dispose()很好,但不知何故,我需要在標籤上使用它。 – miri 2012-08-16 22:48:54

+0

嗯,不,很確定你不想處理這個標籤,那會讓它消失並且使你的代碼崩潰。配置位圖。 – 2012-08-16 23:36:59