2017-11-02 16 views
13

मेरा प्रोग्राम एक सीआरएम है, मैंने रेड रिबन बार का उपयोग किया, इसलिए छवियों के साथ कई बटन, RadGridView (जिसमें कुछ कॉलम छवियां हैं) और कई अन्य नियंत्रण जिनमें शामिल हैं इमेजिस। यह एक एमडीआई माता-पिता/बाल कार्यक्रम है।सिस्टम। मुख्य पर मेमोरी अपवाद से बाहर निकलना() विधि - सी #

Just an Example of RibbonBar

तो कई मामलों में एक एमडीआई बच्चे लोड हो रहा है या कुछ ग्रिड के साथ काम करते हुए देखे गए कार्यक्रम लटका है और मुझे इस त्रुटि दे देंगे:

OutOfMemoryException occurred in System.Drawing.dll 

मैं कुछ भागों, लेकिन कोई सफलता पर GC.Collect() की कोशिश की । छवियों को सेट करने के लिए कोई कोड नहीं है! उदाहरण के लिए एक बटन के लिए एक छवि सेट करने के लिए मैंने दृश्य स्टूडियो में अपनी गुणों का उपयोग किया। मैंने दृश्य मोड में गुण पैनल का उपयोग करके इस तरह अन्य सभी नियंत्रण छवियों को सेट किया है।

enter image description here

और ये ड्राइंग से संबंधित कुछ डिजाइनर कोड हैं:

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

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

और त्रुटि थोड़ी देर के अनुप्रयोग के साथ काम करने के बाद आती है, यह Program.cs में और लाइन Application.Run(new MainForm()); में दिखाई देगा:

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 एमडीआई माता पिता जो रिबन बार होता है।

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:

रिबन पट्टी बटन पर क्लिक करके mdi-children फोन करने के लिए कोड यहाँ है: और इस पूर्ण स्टैक ट्रेस है

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

और यहाँ OpenForm विधि है:

private void OpenForm(Form formType, string Caption) 
{ 
    foreach (Form nform in Application.OpenForms) 
    { 
     if (nform.GetType() == formType.GetType()) 
     { 
      nform.Activate(); 
      return; 
     } 
    } 
    this.MdiChildren.OfType<Form>().ToList().ForEach(x => x.Dispose()); 
    GC.Collect(); 

    Form form = formType; 
    form.MdiParent = this; 
    form.Dock = DockStyle.Fill; 
    form.Show(); 
    this.Text = Caption; 
} 

और प्रत्येक एमडीआई में InitializeComponent(); के बाद बच्चे के फॉर्म कंस्ट्रक्टर, मैंने GC.Collect(); भी लिखा। लेकिन टिप्पणियों में बताया गया है कि, कार्य प्रबंधक में GDI objects बढ़ेगा और 10000 ऑब्जेक्ट तक बढ़ेगा और फिर एप्लिकेशन क्रैश हो जाएगा।

UPADTED: सबसे मुद्दा

ऐसा लगता है मैं हिस्सा जो कारण सबसे GDI objects मिल गया है। प्रत्येक रूप में टेक्स्टबॉक्स, ड्रॉप डाउन सूची आदि जैसे कुछ नियंत्रण होते हैं। मैंने उनके लिए कुछ नियम निर्धारित किए हैं, उदाहरण के लिए यदि उपयोगकर्ता टेक्स्टबॉक्स दर्ज करते हैं, तो इसका पिछला रंग पीला होना चाहिए और छोड़ने के बाद इसे फिर से सफेद होना चाहिए। तो एक मुख्य विधि है जिसे मैं सभी नियंत्रणों के माध्यम से साक्षर लोड करने के लिए फॉर्म लोड में कॉल करता हूं और लक्षित लोगों को ढूंढता हूं और उदाहरण के लिए परिभाषित नियमों के साथ ईवेंट दर्ज करता हूं और छोड़ देता हूं। कुछ इस तरह:

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

और ClassCRMControls वर्ग के अंदर:

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

इस अपवाद के पूर्ण स्टैक ट्रेस लॉग इन करें, शायद यह कुछ सुराग प्रदान करेगा। – Evk

+2

एचएमए, कार्यक्रम में एक खराब हैंडल रिसाव है। यह इतना बुरा है कि अपवाद संवाद भी अब और नहीं दिखाया जा सकता है। यह कार्य प्रबंधक, प्रक्रिया टैब में कुछ ऐसा है जो आप देख सकते हैं। जीडीआई ऑब्जेक्ट्स के लिए कॉलम जोड़ें, आप इसे लगातार बढ़ाएंगे और 10000 तक पहुंचने पर शो खत्म हो जाएगा। कोई भी इन छवियों को निपटाने के लिए कोई पुरस्कार नहीं जीतता है, लेकिन यह घातक नहीं होना चाहिए। आपने पहले ही कहा है कि आपने जीसी.कोलेक्ट() की कोशिश की है, यह मदद नहीं करता है तो फाइनलज़र थ्रेड शायद डेडलॉक हो गया है। अप्रबंधित डीबगिंग सक्षम करें और पता लगाएं कि यह क्या कर रहा है। –

+1

उपयोगकर्ता ऑब्जेक्ट्स कॉलम को भी देखें, उनको लीक करना Wins.s में नियंत्रण और क्लीयर() या निकालें() का उपयोग करके एक और पारंपरिक बग है। –

उत्तर

5

मैं समस्या के स्रोत पाया है और यह मैं ग्रिड और अन्य नियंत्रण के लिए भी इस्तेमाल किया कस्टम एनिमेटेड कर्सर था।मैं इसे इस तरह से प्रारंभ:

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

जब से मैं फ़ाइल हर बार जब मैं किसी भी तरह से इसका इस्तेमाल किया, अधिक से अधिक GDI Objects बना लिया गया है से इस कर्सर लोड।

तो मैं एक public static cursor मुख्य() इस तरह संबंधित फार्म की घोषणा की:

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

और फिर मैं तो बस रूप से इस वस्तु public static cursor संदर्भ जब भी मैं इस कर्सर का उपयोग करने की आवश्यकता है।

this.Cursor = MainForm.animCur; 

है कि यह :)

मैं इसे कैसे पता चला? मैं बस कुछ कोडों को हटाने (टिप्पणी) करने की कोशिश करता हूं जिन्हें मैंने संदेह किया था, फिर मैंने कार्य प्रबंधक में GDI objects की जांच की। कुछ परीक्षणों के बाद यह स्पष्ट हो गया कि नए कर्सर वस्तुओं की अंतहीन लोडिंग समस्या पैदा कर रही थी।

+3

यह एक बहुत ही उपयोगी उत्तर नहीं है। निश्चित रूप से इस क्यू + ए के भविष्य के पाठकों में एक ही समस्या नहीं होगी और यह जानना चाहेंगे कि आपने इस हैंडल रिसाव के कारण को कैसे खोजा। और इसे सही तरीके से करने पर विचार करें ताकि जीसी * सही ढंग से रिसाव से बच सके। नमूना कोड [यहां है] (https://stackoverflow.com/a/4306984/17034), "खुद के हैंडल" फ़ील्ड के साथ हैक इसका ख्याल रखता है। –

+1

भावी पाठकों के लिए ओपी ने अपना जीडीआई ऑब्जेक्ट गिनती विश्लेषण शामिल करने के लिए उत्तर संपादित किया। हंस ने इसकी चर्चा की [यहां] (https://stackoverflow.com/a/8306253/495455), जब आप एप्लिकेशन का उपयोग करते हैं तो जीडीआई गणना का निरीक्षण करते हैं। यह कैसे करें [यहां] (https://stackoverflow.com/a/40232021/495455) –

+1

मैं असहमत हूं, यह एक उपयोगी उत्तर है क्योंकि यह भविष्य के पाठकों को बताता है कि "OutOfMemoryException" में अधिक स्रोत हैं स्मृति शर्तों के बाहर * बस * से त्रुटियों के लिए। यहां जीडीआई हैंडल का रिसाव था, और यदि यह अंततः एक ही अपवाद का कारण बनता है तो यह आपके लिए वर्णित एक उपयोगी स्थिति है। हालांकि, यहां SO पर अन्य प्रश्नोत्तर पोस्ट हैं जो इन चीजों को अधिक विस्तार से बताते हैं। हालांकि यह इस प्रश्न और उसके उत्तर को अमान्य नहीं करता है, शायद यह डुप्लिकेट के रूप में इसे बंद करने के लिए उपयुक्त हो सकता है? –

3

OutOfMemoryExceptions के लिए कई कारण हो सकते हैं। मैंने उनमें से 6 पर चर्चा की है in another question

इस मामले में, टिप्पणियों और संपादन के बाद, यह स्पष्ट हो गया कि जीडीआई मुद्दे भी होते हैं। आप कार्य प्रबंधक में एक अतिरिक्त स्तंभ दिखा कर इन मुद्दों का पता लगाने कर सकते हैं:

GDI objects shown in Task Manager

GDIView GDI रिसाव विश्लेषण के लिए कहीं ज्यादा बेहतर अनुप्रयोग है, क्योंकि यह भी आप GDI संभाल कि खो गया के प्रकार बताता है। इसमें पूर्ण और रिश्तेदार काउंटर भी हैं, ताकि आप देख सकें कि उनमें से कितने विशेष कार्य के दौरान खो जाते हैं।

GDIView details

GDI की संख्या can be configured in Registry संभालती है। स्थायी समाधान के रूप में इसका उपयोग न करें। इसके बजाय, GDIView की अतिरिक्त जानकारी के साथ, कोड का टुकड़ा ढूंढें जो जीडीआई ऑब्जेक्ट को लीक करता है।

जब आप जीडीआई हैंडल की सीमा में भाग लेते हैं, तो एप्लिकेशन आम तौर पर खराब दिखना शुरू कर देता है: चीजें अब और पेंट नहीं होती हैं और आपको कुछ स्थानों में काले आयताकार मिलते हैं। हालांकि, यह व्यवहार जरूरी नहीं है। ओपी के मामले में, काले आयत विवरण का हिस्सा नहीं थे।

संबंधित मुद्दे