系统特定的ListView列宽更改行为

时间:2018-09-28 22:02:32

标签: c# .net winforms

背景:今天早些时候,我发布了一个开源应用程序,它是用C#.NET和WinForms on github编写的。下载它的第一批人发现它在启动时立即崩溃。假设我以某种方式搞砸了发行,我在这里posted a question。一些乐于助人的人下载了该项目,并迅速确定问题是由堆栈溢出引起的。

这样就解决了,但是问题仍然存在:为什么我运行该代码时不会炸毁该代码?

特定问题是由代码导致的,该代码试图在窗口或另一列的大小发生更改时尝试调整详细信息模式ListView最右边列的大小。 ColumnWidthChanged事件处理程序正在设置列的宽度,从而导致无限递归。

在我的系统上,它工作正常(here's video)。一种可能的解释是,我有一个特殊版本的WinForms(或基础控件),如果列宽未更改,它不会发布事件更改通知。

我真正想要的是对在我的系统上工作的代码可以在其他地方工作充满信心。回答了我的问题的人似乎毫不费力地在其开发系统上重现崩溃。我是否成功安装了某种“防弹版”?

应用程序和库项目针对.NET Framework 4.6.1或.NET Standard 2.0。将应用程序更改为目标4.7.1无效。我正在Windows 10 Pro系统上使用通过15.8.3更新的Visual Studio社区2017。这是我第一次尝试使用台式机C#.NET应用程序,因此我可能做一些愚蠢的事情。

更新:受@jwdonahue的评论启发,我进行了一个实验:在事件处理程序中,抓取StackTrace并检查FrameCount,记录看到的最大值。启用列更新之一后,我始终看到最大帧计数为414,其中存在ColumnWidthChanged事件处理程序的多个实例。如果我注释掉列更新,则最大计数下降到174,并且我仅看到该事件的一个实例。

由@LexLi转发的失败运行产生的堆栈跟踪有5087个条目,所以这不是我的堆栈限制更高的简单问题。

1 个答案:

答案 0 :(得分:0)

可能是在您的系统上最终将列宽设置为现有值。如果新值与当前值相同,则它可能不会触发更改的事件。

可能的原因是:

  • 由于DPI不同,启动窗口的大小可能会有所不同。
  • 数据可能会有所不同,从而导致不同系统上的宽度不同。
  • 在出现故障的系统上,宽度可能不会收敛,而是在两个值之间交替变化。
  • 理论上,它可能取决于.net框架或OS的版本。

从实际的角度来看,无论哪种方式,最好将软件设计为没有循环计算。