2009-11-18 67 views
7

首先,我找到了例外的解決方案。我更好奇爲什麼它產生了它所做的特定例外。C#,WinForms:ListBox.Items.Add生成一個OutOfMemoryException,爲什麼?

我的方案,我加入了POCO到ListBox像這樣:

myListBox.Items.Add(myPOCO); 

這是產生OutOfMemoryException。問題是關閉POCO的ToString正在返回null。我添加了一個string.IsNullOrEmpty檢查以返回一個「安全」的值,當null和異常消失時。

爲什麼這會生成OutOfMemoryException而不是別的(比如說NullReferenceException)?

編輯:項目被添加到for循環中。

完整的調用堆棧(刪除公司特定的參考)如下。有一點需要注意 - 當這個被調用時,列表框是空的。

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

您是否在循環中添加項目? – scottm 2009-11-18 17:03:31

+0

在什麼情況下'ToString'返回null?是否當POCO非常大? – 2009-11-18 17:08:05

+0

出於興趣,你能從異常中發佈完整的堆棧跟蹤嗎? – 2009-11-18 17:13:19

回答

12

這是由於的方式System.Windows.Forms.ListBox.NativeAdd方法實現:

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

GetItemText方法,它返回null等物體上使用ToString()一個消息與null參數一起發送,反過來返回一個無效的指針,然後輸入引發異常的第二種情況。

+0

哈,我打算將NativeAdd方法的全部源碼複製到我的答案中,但是決定不這麼做......猜猜我做錯了選擇! :-) – 2009-11-18 19:04:55

+0

@Justin - 我被撕裂了,但我認爲這樣會更好地幫助解決這個問題的其他人。 – 2009-11-18 19:40:33

+0

沒問題,有點競爭讓我們都變得更聰明! :-) – 2009-11-18 20:00:52

9

當底層LB_ADDSTRING的Windows API調用失敗,WinForms的總是返回OutOfMemoryException。在.NET Framework參考源的註釋解釋了原因:

// 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)); 
相關問題