在.NET中显示模态对话框时出现微小闪烁

7
我在我的.NET Windows Forms应用程序中遇到了一个烦人的问题。
我有一个主窗体(A)和一个进度窗体(B),当我启动长时间操作时,它会以模态方式显示。
当操作完成并关闭B时,似乎在几毫秒内将我的应用程序后面的窗口(通常是Skype)带到前面,然后我的应用程序正常激活。
这只是一个小闪烁,但很烦人。这里我写了一些提示,可以帮助找到解决方案:
- 我调用showDialog而没有使用IWin32Window,但添加它并没有成功结果。 - 我使用Close()关闭了B,然后尝试了Hide(),然后是Close(),但没有帮助。 - 执行ShowDialog()的代码从UI线程调用,因此它似乎不是线程问题。
感谢您提供任何线索。提前致谢。

2
不太理解这部分内容:“在几毫秒内被带到”。 - crlanglois
只是为了明确,当B关闭后立即出现闪烁? - NotMe
@crlanglois:这是一个错误。我的意思是“被带到前面……” - Daniel Peñalba
@Chris Lively:是的,就是这样。 - Daniel Peñalba
你解决了这个问题吗? - user448516
显示剩余2条评论
6个回答

4

检查是否没有调用Hide或Close方法。避免闪烁的唯一方法是使用DialogResult。 更新: this.DialogResult = DialogResult.Ok

检查OnFormClosing等处理程序,它们可能包含错误的方法调用。

小技巧是明确设置Owner。

_dialog.Owner = this;
_dialog.ShowDialog();

正在编辑此帖的人 - _dialog.ShowDialog(this) 的工作方式有些不同。请查看反编译代码中的 owner = ((Control) owner).TopLevelControlInternal;

由某人编辑:

或者...

_dialog.ShowDialog(this);

根据MSDN,这些调用是相同的


我刚刚通过注释Hide和Close来解决了闪烁问题。 - user448516
嗨Mad,我不明白,我调用的是Close()而不是Hide(),但我需要调用Close()来关闭对话框,请问你能否更好地解释一下你的答案?谢谢! - Daniel Peñalba
关闭对话框的正确方式是:this.DialogResult = DialogResult.Ok。 - user448516
在调用ShowDialog之前,您是否禁用了主窗体?这可能会导致闪烁。 - user448516
只有将 MyDialog.Hide() 替换为 MyDialog.DialogResult = DialogResult.OK 才能解决问题! - MaxAlex

4

我曾经遇到过同样的症状,让我感到很烦恼。

最后我发现问题出在我调用了this.Dispose()而不是this.Close()来关闭模态窗口。我不确定为什么一开始会调用this.Dispose()

切换方法后,问题消失了。

我意识到这个帖子已经老旧了,这不是你遇到问题的原因,我只是想帮助那些犯了和我一样错误的人。


1
  1. 不要在模态窗口上调用Close(它将无法释放并且会导致内存泄漏)

  2. 设置this.DialogResult = DialogResult.OK

  3. 从父窗口调用Dispose(),永远不要从即将关闭的窗体中调用

  4. 记得在Dispose(bool)中释放所有由窗体IContainer持有的组件(VS Designer实现的Dispose(bool)通常不足以避免内存泄漏)


1
在我的情况下,我在VB.Net窗体应用程序中也遇到了同样的问题,但场景有所不同。我有一个用户控件,它使用showdialog()打开一个对话框,称为dialog1,填写一些数据后,它隐藏dialog1并再次使用showdialog()打开dialog2。
在隐藏dialog1和显示dialog2的过程中,会出现闪烁,并且在一瞬间显示窗口背景。
尝试了许多解决方案和变通方法,但都没有成功。我自己找到了一个解决方法,可能会帮助其他人。
隐藏dialog1时,我正在使用Me.Hide(),解决方法是改变窗体的不透明度而不是调用Hide()方法。
' Me.Hide() Me.Opacity = 0
通过这个变通方法,应用程序可以正常工作,没有任何闪烁问题。
PS:上述代码行是VB.Net的,但足以让.NET窗体应用程序开发人员了解如何解决此问题。

1
这太棒了。简单的修复方法,而且是唯一对我有效的方法。谢谢! - PerpetualStudent

0
你可以尝试使用这个示例来对你的窗体进行双缓冲:

这通常可以消除屏幕更新时的闪烁。


0

好的,听起来像是:

  1. 在主窗口用户开始一个长时间操作
  2. 你显示一个进度模态窗口
  3. 操作完成后你关闭进度窗口
  4. 你的主窗口不会立即显示,相反,在一秒钟或更短的时间内,它会透露出后面的东西。
  5. 你的主窗口完成了重绘操作,并且完全可见。
  6. 当你有应用程序,如 Skype 运行时,这种情况发生得更频繁。

如果是这样的话,就有许多不同的可能原因。例如,你的视频驱动程序可能存在错误,在某些情况下会导致屏幕外合成延迟。

系统本身甚至可能正在经历阻塞 CPU 操作。这是由于代码关闭对话框并返回主表单所需的时间引起的。你可以查看一下,在进度条关闭和将 UI 控件返回给用户之间,是否还有其他操作。

系统可能只是受到内存限制,而你的操作会导致大量的交换到磁盘上。当操作完成时,Windows 可能会通知需要从磁盘中拉回以前交换出去的内存并将其推回 RAM 中,从而导致延迟。


我建议你只运行应用程序和任务管理器或资源监视器,看看会发生什么。如果问题不再出现,则考虑为您的机器添加更多内存,或者忽略它。

如果问题仍然存在,并且您的内存使用几乎没有剩余空间,那么再次添加内存或忽略它。

如果问题仍然存在,但内存使用率很低,请调查您的代码,看看在对话框关闭并将控制权交还给用户之间您正在做什么。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接