向.NET Windows窗体(C#)添加大量控件时出现问题
我有一个用C#编写的Windows Form应用程序。它的工作是将消息发送到用户列表。在发送这些消息时,我想显示每个用户的操作状态。我正在为每个用户做的是创建一个Label控件并将其添加到Panel中。对于一小部分用户来说,这没有问题。当我将大小增加到1000或者更大时,Visual Studio调试器将显示以下消息:
A first chance exception of type 'System.ComponentModel.Win32Exception' occurred in System.Windows.Forms.dll A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
然后,应用程序挂起。关于我在做什么错以及如何解决此问题的任何想法?
解决方案
这是一种变通方法,但是我认为用户并不真正希望查看1000人的列表。向他们显示其余的当前/最新和摘要报告。或者让他们翻页。
改用DataGridView
给定大小,我会考虑在RichTextBox中显示状态。
发生的情况是我们生成了太多的句柄,而Framework无法全部处理它们。
控件太多!使一个控件包含所有这些状态消息。多行文本框怎么样?
没有看到特定的代码,很难分辨。如果我承担了同一个程序的任务,那么我将采取不同的方法。
我将使用Grid或者Listview来显示用户及其正在发送的消息的状态。这些控件可以处理无限数量的行(受系统内存限制)。每个用户一行(或者每条消息一行-效果更好)。
这应该是UI线程中唯一发生的事情。使用后台工作程序(BacngroundWorker类)或者消息队列框架(MSMQ,SQL Server)使消息异步发送,并通过BackgroundWorker备份状态报告。
至于特定错误-我不知道我们为什么得到它。我们可以在WinForm上放置的标签数量应该没有限制。我怀疑该错误是由其他原因引起的。
如果我们仅在面板上显示标签,则建议我们使用GDI显示状态。在OnPaint中写入可见区域的文本,并仅在状态标签发生变化时使状态标签的区域无效。
而是将ProgressBar放在窗体上。如果我们要向1000个人发送一条消息,则每次发送一条消息时,只需将ProgressBar加1.
如果我们要向1000个人发送5则消息,请为消息提供一个进度条,为人们提供一个进度条(第二条将为第一个条上的每个值循环一次其值)。
我们还可以为每个进度条贴上标签(例如"完成95%"或者"消息3之5"或者其他内容)。
我们不能在.NET表单上拥有如此众多的控件,即使可以,也没有任何用户可以同时查看所有控件。
我喜欢在详细信息模式下使用ListView。通常,我将创建一个例程以添加一行,使其处于选中状态,然后在该项目上调用EnsureVisible()
以自动滚动至该行。
如前所述,控件与一个或者多个窗口句柄相关,并且操作系统只能分发很多。