2017-11-02 165 views
13

Programım bir CRM, Rad Şerit Çubuğunu kullandım, bu yüzden görüntüleri olan birçok Düğme, RadGridView (bazı sütunlar resim içeriyor) ve diğer birçok denetim içerir. Görüntüler. Bir mdi ebeveyn/çocuk programı.System.Drawing Out of Memory Exception On Main() Metodu - C#

OutOfMemoryException occurred in System.Drawing.dll 

ben belirli bölümlerine ama hiçbir başarısı üzerine GC.Collect() çalıştı: bu kadar çok durumda

Just an Example of RibbonBar

bir mdi çocuğu yükleme ya da bazı ızgara ile çalışırken programın asmak ve bana bu hatayı verecektir görüyor . Görüntüleri ayarlamak için kod yok! Örneğin bir görüntü için bir görüntü ayarlamak için görsel stüdyosunda özelliklerini kullandım. Diğer kontrol resimlerini görsel modda özellikler panelini kullanarak bu şekilde ayarladım.

enter image description here

ve Bunlar çizim ile ilgili bazı tasarımcı kodlardır:

btnCustomerList.Image = global::MyApp.Properties.Resources.CustomerList32; 

    gridViewCommandColumn1.Image = global::MyApp.Properties.Resources.ViewShop32; 

ve hata uygulaması ile çalışan bir süre sonra gelince, Program.cs ve hat Application.Run(new MainForm()); görünecektir:

static void Main() 
    { 
     AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", AppDomain.CurrentDomain.BaseDirectory + "\\Settings.config"); 
     bool ok; 
     Mutex m = new Mutex(true, WindowsIdentity.GetCurrent().Name.ToString().Split('\\')[1] + "MyApp", out ok); 
     if (ok) 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 

      // The Error will cause HERE 
      Application.Run(new MainForm()); 

      GC.KeepAlive(m); 
     } 
     else 
      Application.Exit(); 
    } 

MainForm Şerit Bar içeren mdi üstüdür.

at System.Drawing.Image.FromHbitmap(IntPtr hbitmap, IntPtr hpalette) 
at System.Drawing.Image.FromHbitmap(IntPtr hbitmap) 
at System.Drawing.Icon.ToBitmap() 
at System.Windows.Forms.ThreadExceptionDialog..ctor(Exception t) 
at System.Windows.Forms.Application.ThreadContext.OnThreadException(Exception t) 
at System.Windows.Forms.Control.WndProcException(Exception e) 
at System.Windows.Forms.Control.ControlNativeWindow.OnThreadException(Exception e) 
at System.Windows.Forms.NativeWindow.Callback(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 MyApp.Program.Main() in d:\\MyApp\\Application\\MyApp\\Program.cs:line 36" 

UPADTED:

şerit çubuğu düğmeleri tıklayarak mdi-children çağırmak için kod buradadır: ve bu Tam yığın takibi İşte

private void btnCustomerList_Click(object sender, EventArgs e) 
{ 
    OpenForm(new FormCustomerList(), "Customer List"); 
} 

private void btnCustomerRelated_Click(object sender, EventArgs e) 
{ 
    OpenForm(new FormCustomerRelated(), "Customer Related"); 
} 

ve OpenForm yöntemdir:

Her mdi içinde

çocuğun form kurucusu, InitializeComponent();'dan sonra da GC.Collect(); yazdım. Ancak yorumlarda belirtildiği gibi, görev yöneticisinde GDI objects nesneler artacak ve 10000 nesnelere kadar artacak ve uygulama çökecektir.

UPADTED: Ben en çok GDI objects neden parçasını bulduk görünüyor EN SAYI

. Her formda, metin kutuları, açılan liste vb. Gibi bazı kontroller vardır. Bunlar için bazı kurallar koymuştum. Örneğin, kullanıcı bir metin kutusu girerse, arka rengi sarı olmalı ve sonra tekrar beyaz olmalıdır. Bu yüzden, tüm kontroller aracılığıyla okur-yazar olmak için hedef yükü dediğim ve hedefleri bulup, tanımlanmış kurallarla etkinliklere giriş ve çıkış eklediğim temel bir yöntem var. Bu gibi bir şey:

private void FormCustomerList_Load(object sender, EventArgs e) 
{ 
    ClassCRMControls.AddEventHandler(this); 
} 

ve sınıf ClassCRMControls iç:

public static void AddEventHandler(Control parent) 
{ 
    foreach (Control c in parent.Controls) 
    { 
     if (c.GetType() == typeof(RadTextBox)) 
     { 
      c.Enter += new EventHandler(ClassCRMControls.EnterEvent); 
      c.Leave += new EventHandler(ClassCRMControls.LeaveEvent); 
     } 
     else 
      AddEventHandler(c); 
    } 
} 

private static void EnterEvent(object sender, EventArgs e) 
{ 
    (sender as RadTextBox).TextBoxElement.TextBoxItem.BackColor = Color.FromArgb(255, 251, 147); 
} 

private static void LeaveEvent(object sender, EventArgs e) 
{ 
     (sender as RadTextBox).TextBoxElement.TextBoxItem.ResetValue(LightVisualElement.BackColorProperty, ValueResetFlags.Local); 
} 
+0

Bu özel durumun tam yığın izini günlüğe kaydet, belki bir ipucu verir. – Evk

+2

Hmya, programın hatalı bir tanıtıcı sızıntısı var. İstisna diyaloğu bile artık gösterilemeyecek kadar kötü. Görev Yöneticisi, İşlemler sekmesinde görebileceğiniz bir şey. GDI Nesneleri için sütun ekleyin, sürekli olarak arttığını görürsünüz ve 10000'e gelindiğinde şov biter. Bu görüntüleri imha etmedikleri için kimse ödül kazanmaz, ancak ölümcül olmamalıdır. GC.Collect() yöntemini denediğinizi zaten söylüyordunuz, o zaman bu sonuç vermez, sonuçta sonlandırıcı parçacığı muhtemelen kilitleniyor. Yönetilmeyen hata ayıklamayı etkinleştirin ve ne yaptığını öğrenin. –

+1

Ayrıca, Controls.Clear() veya Remove() işlevinin neden olduğu Winform'lardaki başka bir geleneksel hatanın sızmasını sağlayan USER Objects sütununa da bakın. –

cevap

5

Ben sorunun kaynağını bulduk ve ben de ızgaraları ve diğer kontroller için kullanılan özel animasyonlu imleç oldu.Böyle başlatılamıyor:

this.Cursor = ClassObjects.CreateAnimatedCursor("C:\\aniCur.ani")); 

Ben herhangi bir şekilde kullanılan her zaman, daha GDI Objects daha yarattı var dosyadan bu imleci yüklenen beri.

Yani() Böyle İlgili formun ana bir public static cursor ilan:

public static Cursor animCur = ClassObjects.CreateAnimatedCursor("C:\\aniCur.ani")); 

ve bu imleci kullanmak gerektiğinde o zaman sadece formdan bu nesneyi public static cursor başvuru. Bu

:) var

this.Cursor = MainForm.animCur; 

bunu nasıl buldular? Sadece şüphelendiğim bazı kodları kaldırmaya (yorum yapmaya) çalışıyorum, sonra GDI objects'u görev yöneticisinde kontrol ettim. Bazı testlerden sonra, yeni imleç nesnelerinin sonsuz yüklenmesinin soruna neden olduğu ortaya çıktı.

+3

Bu çok yararlı bir cevap değil. Elbette, bu Q + A'nın gelecekteki okuyucuları aynı soruna sahip olmayacak ve bu tutamak sızıntısının nedenini nasıl keşfettiğinizi bilmek isteyeceklerdir. Ve bunu doğru bir şekilde yapmayı düşünün, böylece GC * kaçaktan doğru bir şekilde kaçınılabilir. Örnek kod [burada] (https://stackoverflow.com/a/4306984/17034), "ownHandle" alanına sahip hack bununla ilgilenir. –

+1

Gelecek okuyucular için, kendi GDI Nesne sayımı analizini içerecek şekilde OP'yi düzenlediniz. Hans, uygulamayı kullanırken GDI Sayısını gözlemleyerek [burada] (https://stackoverflow.com/a/8306253/495455) tartıştı. Bunun nasıl yapılacağı hakkında daha fazla bilgi ve adım var (https://stackoverflow.com/a/40232021/495455) –

+1

Katılmıyorum, gelecekteki okuyuculara "OutOfMemoryException" ın daha fazla kaynağa sahip olduğunu bildirdiği için bu yararlı bir cevaptır. Hatalardan * sadece * bellek koşullarının dışında. Burada GDI saplarının bir sızıntısı vardı ve eğer bu sonuçta aynı istisnaya neden olursa, o zaman size tarif edilmiş olan yararlı bir durumdur. Ancak, burada, bu şeyleri daha ayrıntılı olarak açıklayan diğer Soru-Cevap mesajları vardır. Bu, bu soruyu ve cevabını geçersiz kılmasa da, belki de bir kopya olarak kapatmak için faydalı olabilirdi? –

3

OutOfMemoryExceptions için birden çok neden olabilir. Bunlardan 6'sı in another question'u tartıştım.

Bu durumda, yorumlardan ve düzenlemeden sonra, GDI sorunlarının da ortaya çıktığı anlaşılmıştır. Sen görev yöneticisinden ek bir sütun göstererek bu sorunları tespit edebilir:

GDI objects shown in Task Manager

GDIView GDI Kaçak analizi için çok daha iyi bir uygulamadır, ancak aynı zamanda kayboldu GDI sapın türünü anlatır çünkü. Ayrıca mutlak ve göreceli sayaçlara sahiptir, böylece belirli bir eylem sırasında kaçının kaybolduğunu görebilirsiniz.

GDIView details

GDI sayısı can be configured in Registry yönetir. Bunu kalıcı bir çözüm olarak kullanmayın. Bunun yerine, GDIView'den ek bilgi ile GDI nesnesini akıtan kod parçasını bulun.

GDI tutamaçları sınırına girdiğinizde, uygulama genellikle kötü görünmeye başlar: işler artık boyanmaz ve bazı yerlerde siyah dikdörtgenler alırsınız. Ancak, bu davranış gerekli değildir. OP'nin durumunda, siyah dikdörtgenler açıklamanın bir parçası değildi.