C#,WinForms:ListBox.Items.Add生成OutOfMemoryException,为什么?
首先,我找到了异常的解决方案。我更好奇的是,为什么它会生成它所做的特定异常 在我的场景中,我向一个列表框中添加一个,如下所示:C#,WinForms:ListBox.Items.Add生成OutOfMemoryException,为什么?,c#,winforms,C#,Winforms,首先,我找到了异常的解决方案。我更好奇的是,为什么它会生成它所做的特定异常 在我的场景中,我向一个列表框中添加一个,如下所示: myListBox.Items.Add(myPOCO); 这正在生成一个OutOfMemoryException。问题是ToString关闭POCO返回null。我添加了一个字符串.IsNullOrEmpty检查,以在null和异常消失时返回一个“安全”值 为什么这会生成一个OutOfMemoryException,而不是其他东西(比如NullReferenceExc
myListBox.Items.Add(myPOCO);
这正在生成一个OutOfMemoryException
。问题是ToString
关闭POCO返回null
。我添加了一个字符串.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()
System.OutOfMemoryException未处理
Message=“列表框包含的项目太多。”
Source=“System.Windows.Forms”
堆栈跟踪:
位于System.Windows.Forms.ListBox.NativeAdd(对象项)
位于System.Windows.Forms.ListBox.ObjectCollection.AddInternal(对象项)
位于System.Windows.Forms.ListBox.ObjectCollection.Add(对象项)
在\.cs中加载(对象发送方,事件参数e):第52行
在System.Windows.Forms.Form.OnLoad(EventArgs e)中
在System.Windows.Forms.Form.OnCreateControl()中
位于System.Windows.Forms.Control.CreateControl(布尔值不可修改)
在System.Windows.Forms.Control.CreateControl()中
在System.Windows.Forms.Control.WmShowWindow(Message&m)中
位于System.Windows.Forms.Control.WndProc(Message&m)
在System.Windows.Forms.ScrollableControl.WndProc(Message&m)中
在System.Windows.Forms.ContainerControl.WndProc(Message&m)中
在System.Windows.Forms.Form.WmShowWindow(消息和消息)
在System.Windows.Forms.Form.WndProc(Message&m)中
在System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&m)中
在System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&m)中
在System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd、Int32 msg、IntPtr wparam、IntPtr lparam)
位于System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd,Int32 nCmdShow)
位于System.Windows.Forms.Control.SetVisibleCore(布尔值)
位于System.Windows.Forms.Form.SetVisibleCore(布尔值)
在System.Windows.Forms.Control.set_可见(布尔值)
位于System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32原因,ApplicationContext上下文)
位于System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32原因,ApplicationContext上下文)
在System.Windows.Forms.Application.RunDialog(表单)中
位于System.Windows.Forms.Form.ShowDialog(iwin32窗口所有者)
在System.Windows.Forms.Form.ShowDialog()中
\Program.cs中的at.Program.Main():第25行
位于System.AppDomain.\u nexecutestAssembly(程序集,字符串[]args)
位于System.AppDomain.nExecuteAssembly(程序集,字符串[]args)
at System.Runtime.Hosting.ManifestRunner.Run(布尔checkAptModel)
在System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly()上
在System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext ActivationContext,String[]activationCustomData)中
位于System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext ActivationContext)
位于System.Activator.CreateInstance(ActivationContext ActivationContext)
位于Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone()处
位于System.Threading.ThreadHelper.ThreadStart\u上下文(对象状态)
在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态)
位于System.Threading.ThreadHelper.ThreadStart()处
当底层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));
这是因为
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;
}
该方法对返回
null
的对象使用ToString()
,因此发送带有null
参数的消息,这反过来又返回一个无效指针,您将进入引发异常的第二个案例。如果出现此类错误,请仔细检查调用listbox.Items.Add
或listbox.DataSource=xxxxx
。添加或绑定到列表框的任何对象
类型必须在ToString()
方法中返回非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;
}
}
//listbox.Items.Add(new MyItem());
//--或--
//DataSource=new List(){new MyItem()};
公共类MyItem
{
公共字符串名称{get;set;}
公共字符串标签{get;set;}
公共重写字符串ToString()
{
//如果不添加以下两行,则可能会抛出listbox.Items.Add或listbox.DataSOurce=somelist中的OutOfMemoryException
if(string.IsNullOrEmpty(Label))//添加此检查以避免
返回此.GetType().Name;//返回string.Empty或其他非null值,否则在将此对象添加或绑定到listbox时,将出现OutOfMemoryException错误
退货标签;
}
}
是否将项目添加到循环中?在什么情况下,ToString
将返回null?是在POCO非常大的时候吗?出于兴趣,您可以发布来自异常的完整堆栈跟踪吗?ToString
返回null,因为我是careles