2009-11-18 76 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)); 
相关问题