代码之家  ›  专栏  ›  技术社区  ›  Austin Salonen gmlacrosse

C#,WinForms:ListBox.Items.Add生成OutOfMemoryException,为什么?

  •  7
  • Austin Salonen gmlacrosse  · 技术社区  · 15 年前

    首先,我找到了异常的解决方案。我更好奇 它生成了它所做的特定异常。

    在我的场景中,我添加了一个 POCO 对于这样的列表框:

    myListBox.Items.Add(myPOCO);
    

    OutOfMemoryException . 问题是 ToString 波科回来了 null string.IsNullOrEmpty 检查以在null和异常消失时返回“安全”值。

    为什么这会产生一个 OutOfMemoryException 而不是别的(比如 NullReferenceException

    编辑

    完整的调用堆栈(特定于公司的引用已删除)如下所示。需要注意的一点是,调用此函数时,列表框为空。

    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()
    
    2 回复  |  直到 15 年前
        1
  •  20
  •   Darin Dimitrov    15 年前

    这是因为方式 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 方法使用 ToString() 在返回的对象上 null 因此,会发送一条消息 无效的

        2
  •  10
  •   Justin Grant    15 年前

    当潜在的 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)); 
    
        3
  •  0
  •   helvete user3408541    4 年前

    listbox.Items.Add listbox.DataSource = xxxxx Object 类型已添加或绑定到列表框中,列表框中必须返回非Null ToString() 方法。默认情况下,如果不重写,则.net将返回类型名称 ToString() 方法。

    如果您已经实现了自己版本的 (使用override关键字)然后确保该方法具有fail-safe以返回非空字符串。请参阅下面的示例,了解如何添加额外的两行,以避免许多人会发现完全误导的这种奇怪错误。

    //listbox.Items.Add(new MyItem());
    //--or--
    //listbox.DataSource= new List<MyItem>(){ new MyItem() };
    
    public class MyItem
    {
        public string Name { get; set; }
        public string Label { get; set; }
    
        public override string ToString()
        {
            //Not adding below 2 lines might throw OutOfMemoryException in listbox.Items.Add or listbox.DataSOurce = somelist
            if (string.IsNullOrEmpty(Label)) //Added this check to avoid 
                return this.GetType().Name; //Return string.Empty or something other than null else you will get OutOfMemoryException error when you add or bind this object to listbox
    
            return Label;
        }
    }