GroupBoxes 和 NumericUpDowns 的 .NET 图形问题
我们遇到了某种图形问题,似乎与 .NET 运行时有关。有时,我们应用程序中所有 GroupBox 的边框和所有 NumericUpDown 的箭头都会消失。似乎他们出于某种原因停止重新绘制,因为 NumericUpDowns 有时在箭头应该在的地方有图形垃圾。
我们怀疑该错误是在多次重新启动应用程序后发生的。一旦出现问题,重新启动应用程序就没有帮助。但是关闭所有 .NET 进程并重新启动应用程序会使问题消失,这表明 .NET 运行时存在问题。
我们的应用程序是使用 VS 2008 SP1 开发的 WinForms 应用程序,面向 .NET 3.5。它以经典模式(客户公司策略)在 Windows XP SP3 上运行。
我搜索过其他有类似问题的人,但大多数命中都涉及 GroupBox 的自定义绘制事件。我们的控件是简单的标准 - 根本不使用绘制事件。
编辑:我如何故意耗尽桌面堆来重现问题?我一直在疯狂地使用任务管理器和 GdiUsage 创建笔、画笔和字体。当然不是调用 dispose,而是将它们存储在列表中以避免垃圾收集。尽管如此,在创建了 100 000 支具有随机颜色的笔之后,根据监视器工具,我只有一些对象。
List<Pen> pens = new List<Pen>();
Random rnd = new Random();
for(int i = 0; i < 100000; i++)
pens.Add(new Pen(Color.FromArgb(rnd.Next())));
We're having some kind of graphics problem which seem to be related to the .NET runtime. Once in a while, the borders of all GroupBoxes and the arrows of all NumericUpDowns in our application dissappears. It seems like they stop repainting for some reason, because the NumericUpDowns sometimes have graphics garbage where the arrows should be.
We suspect that the error occurs after restarting the application several times. Once the problem is present, restarting the application doesn't help. But closing all .NET processes and restarting the application makes the problem disappear, this points toward a problem in the .NET runtime.
Our application is a WinForms app developed using VS 2008 SP1 and targets .NET 3.5. It runs on Windows XP SP3 in classic mode (client company policy).
I've searched for others having similar problems, but most hits involve custom paint events for GroupBoxes. Our controls are plain standard - no paint events are used at all.
EDIT: How can I deliberately exhaust the desktop heap to reproduce the problem? I've been playing with Task Manager and GdiUsage while creating pens, brushes and fonts like crazy. Not calling dispose of course, but also storing them in a list to avoid garbage collection. Still, after creating 100 000 pens with random colors I just have a few objects according to the monitor tools.
List<Pen> pens = new List<Pen>();
Random rnd = new Random();
for(int i = 0; i < 100000; i++)
pens.Add(new Pen(Color.FromArgb(rnd.Next())));
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是程序泄漏句柄的明显迹象。 Windows 为计算机上运行的所有程序维护 GDI 和用户对象的堆。每个进程都有 10,000 个句柄的配额,但一些泄漏或繁重的程序可能会使堆填满。一旦发生这种情况,对笔绘制边框(例如)的请求将失败,并且内容将停止绘制。这并不总是被检查,特别是在本机代码中。
您可以使用 Taskmgr.exe 的“进程”选项卡对其进行诊断。使用“视图”+“选择列”并勾选“句柄”、“用户对象”和“GDI 对象”。留意一个程序,它有很多这样的(数百个),并且在您使用该程序时数量稳步增加。
当您不对笔、画笔、字体、位图等一次性对象使用 Dispose() 或 using 语句时,.NET 程序中的句柄可能会泄漏。当该程序没有使用足够的内存来触发垃圾收集时,以便终结器可以释放句柄。
This is the telltale sign of a program that is leaking handles. Windows maintains a heap for GDI and User objects for all programs running on the machine. There's a quota of 10,000 handles for each individual process but a couple of leaking or heavy programs can get the heap filled to capacity. Once that happens, requests for a pen to draw a border (for example) will fail and stuff stops getting painted. This isn't always checked, particularly in native code.
You can diagnose it with Taskmgr.exe, Processes tab. Use View + Select Columns and tick Handles, USER Objects and GDI Objects. Watch for a program that has a lot of these (hundreds) and has steadily increasing numbers while you use the program.
You can leak handles in a .NET program when you don't use Dispose() or the using statement on disposable objects like pens, brushes, fonts, bitmaps. And when that program doesn't otherwise use enough memory to trigger a garbage collection so that the finalizer can release the handle.