我在Compact Framework中遇到了一个奇怪的表单绘制问题。我有一个登录对话框,基本上是一个小表单,使用ShowDialog打开另一个。刷卡时,应该关闭登录对话框,然后执行一些登录任务,然后激活后面的表格。问题是登录对话框后面的表单没有刷新,因此在某些用户操作刷新后面的表单后才会删除登录对话框。这可能是由于登录任务部分中的繁重处理,但我找不到解决此问题的方法。
基本上,在执行繁重的登录任务之前,我想要一种强制应用程序关闭对话框并再次绘制所有内容的方法。我尝试了很多刷新方法而没有任何运气:
Form loginDialog = new Form();
DialogResult result = loginDialog.ShowDialog();
loginDialog.Dispose();
//I've tried everything at this point to get the form to refresh before performing
//login tasks
this.Refresh();
this.Invalidate();
Application.DoEvents();
PerformHeavyLoginTasks();
有谁知道会出现什么问题?感谢
答案 0 :(得分:1)
好的,我想出来了。问题在于背景窗体上的自定义控件,它使用矩形等手动绘制自己。我认为这是一个紧凑的框架错误,因为我在该控件上调用了Refresh和Invalidate,它应该重新绘制。我必须创建一个方法来直接调用控件的OnPaint覆盖,因为Invalidate和Refreshed几乎被忽略了。
答案 1 :(得分:0)
我认为,这个问题是你在这里没有完全理解系统方面的情况。
当你的前窗(对话框)被解除时,背景窗口(表格)被赋予focu和tol以重新绘制对话框所在的剪辑区域。这通过PostMessage调用发生,该调用发送一个Windows消息,该消息必须在Application.Run调用的内容中弹出,翻译和调度。
按照设计,这是一个相当慢的过程,因为用户界面不应该抢占重要的事情。
如果你在PostMessage发生后立即进行大量处理,那么这些窗口消息的处理通常会变慢,最终导致UI显示为“已锁定”或绘制速度非常慢。如果您正在进行的处理与UI处于同一个线程,则会加剧这种情况。
为什么你的努力没有让事情变得更好?
那么我们如何“修复”这个呢?
第一步通常是将处理放在一个单独的线程上,以允许调度程序在UI和处理线程之间循环执行任务,直到默认量程。 Thgis意味着在允许某种绘图发生之前,处理只能使UI饿死最多100ms(假设线程优先级相等)。
new Thread(PerformHeavyLoginTasks)
{
IsBackground = true
}.Start();
您可以更进一步,让UI在处理过程中“快速启动”(本例中为10ms):
new Thread(new ThreadStart(delegate
{
Thread.Sleep(10);
PerformHeavyLoginTasks();
}))
{
IsBackground = true
}.Start();
当然,这可能意味着如果要显示的UI依赖于处理结果,您现在需要异步处理下一个“显示”。有很多异步模式的在线资源,所以我不会在这里击败那匹死马。