2009-11-18 6 views
7

Zunächst habe ich die Lösung für die Ausnahme gefunden. Ich bin neugieriger warum es erzeugte die spezifische Ausnahme, die es tat.C#, WinForms: ListBox.Items.Add generiert eine OutOfMemoryException, warum?

In meinem Szenario ein POCO zu einem ListBox Ich füge etwa so:

myListBox.Items.Add(myPOCO); 

Dies war ein OutOfMemoryException zu erzeugen. Das Problem war, dass ToString aus dem POCO null zurückgegeben wurde. Ich fügte eine string.IsNullOrEmpty Prüfung hinzu, um einen "sicheren" Wert zurückzugeben, wenn null und die Ausnahme wegging.

Warum generiert dies eine OutOfMemoryException und nicht etwas anderes (etwa NullReferenceException)?

BEARBEITEN: Elemente werden in einer for-Schleife hinzugefügt.

Vollständige Anrufliste (firmenspezifische Referenzen entfernt) ist unten. Eine Sache zu beachten - das Listenfeld ist leer, wenn dies aufgerufen wird.

System.OutOfMemoryException was unhandled 
    Message="List box contains too many items." 
    Source="System.Windows.Forms" 
    StackTrace: 
     at System.Windows.Forms.ListBox.NativeAdd(Object item) 
     at System.Windows.Forms.ListBox.ObjectCollection.AddInternal(Object item) 
     at System.Windows.Forms.ListBox.ObjectCollection.Add(Object item) 
     at <FORM>_Load(Object sender, EventArgs e) in <PATH>\<FORM>.cs:line 52 
     at System.Windows.Forms.Form.OnLoad(EventArgs e) 
     at System.Windows.Forms.Form.OnCreateControl() 
     at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible) 
     at System.Windows.Forms.Control.CreateControl() 
     at System.Windows.Forms.Control.WmShowWindow(Message& m) 
     at System.Windows.Forms.Control.WndProc(Message& m) 
     at System.Windows.Forms.ScrollableControl.WndProc(Message& m) 
     at System.Windows.Forms.ContainerControl.WndProc(Message& m) 
     at System.Windows.Forms.Form.WmShowWindow(Message& m) 
     at System.Windows.Forms.Form.WndProc(Message& m) 
     at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
     at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
     at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
     at System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow) 
     at System.Windows.Forms.Control.SetVisibleCore(Boolean value) 
     at System.Windows.Forms.Form.SetVisibleCore(Boolean value) 
     at System.Windows.Forms.Control.set_Visible(Boolean value) 
     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.RunDialog(Form form) 
     at System.Windows.Forms.Form.ShowDialog(IWin32Window owner) 
     at System.Windows.Forms.Form.ShowDialog() 
     at <APP>.Program.Main() in <PATH>\Program.cs:line 25 
     at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) 
     at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args) 
     at System.Runtime.Hosting.ManifestRunner.Run(Boolean checkAptModel) 
     at System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly() 
     at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData) 
     at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext) 
     at System.Activator.CreateInstance(ActivationContext activationContext) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone() 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
+1

Fügen Sie die Elemente in einer Schleife hinzu? – scottm

+0

Unter welchen Umständen würde 'ToString' null zurückgeben? Ist es, wenn der POCO außerordentlich groß ist? –

+0

Interessant, können Sie die vollständige Stapelüberwachung von der Ausnahme buchen? –

Antwort

12

Dies wegen der Art und Weise ist System.Windows.Forms.ListBox.NativeAdd Methode implementiert:

private int NativeAdd(object item) 
{ 
    int num = (int) base.SendMessage(0x180, 0, base.GetItemText(item)); 
    switch (num) 
    { 
     case -2: 
      throw new OutOfMemoryException(); 

     case -1: 
      throw new OutOfMemoryException(SR.GetString("ListBoxItemOverflow")); 
    } 
    return num; 
} 

Die GetItemText Methode verwendet ToString() auf dem Objekt, das null und so gibt Eine Nachricht wird mit dem Parameter null gesendet, der wiederum einen ungültigen Zeiger zurückgibt, und Sie geben den zweiten Fall ein, der die Ausnahme auslöst.

+0

Hah, ich wollte die gesamte Quelle der NativeAdd-Methode in meine Antwort kopieren, entschied mich aber dagegen ... denke, ich habe die falsche Wahl getroffen! :-) –

+0

@Justin - Ich war zerrissen, aber ich denke, das würde besser jemand anderem helfen, der dieses Problem bekommt. –

+0

kein Problem, ein kleiner Wettbewerb macht uns alle schlauer! :-) –

9

Wenn die zugrunde liegenden LB_ADDSTRING Windows-API-Aufruf fehlschlägt, gibt WinForms immer ein OutOfMemoryException. Ein Kommentar in der .NET Framework-Referenzquelle erklärt, warum:

// On some platforms (e.g. Win98), the ListBox control 
// appears to return LB_ERR if there are a large number (>32000) 
// of items. It doesn't appear to set error codes appropriately, 
// so we'll have to assume that LB_ERR corresponds to item 
// overflow. 
// 
throw new OutOfMemoryException(SR.GetString(SR.ListBoxItemOverflow));