我正在尝试为我的应用程序添加表单兑现模块,我实现了这个msdn示例:Form Stacking and Caching
对于那些无法下载示例的人,这是包含我所指代码的类:
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Threading;
namespace GUIFramework {
public class FormStack : CollectionBase {
private System.Collections.ArrayList stack = new ArrayList();
public void Run() {
do {
System.Windows.Forms.Application.DoEvents();
} while(List.Count > 0);
}
public void Stop() {
// nicely destroy each Form
foreach(StackForm sf in List) {
sf.Dispose();
}
// clear the list to kill the message pump in Run()
List.Clear();
}
public void Push(Type FormType) {
// only allow 1 Push at a time to maintain cache and stack itegrity
Monitor.Enter(this);
foreach(StackForm sf in List) {
if(sf.GetType().Name.Equals(FormType.Name)) {
// form is cached so display cached version
sf.Visible = true;
// add it to the stack
stack.Add(FormType.Name);
return;
}
}
// the Form wasn't cached, so create it
StackForm form = Preload(FormType);
// display it
form.Visible = true;
// add a close event handler
form.FormClosed += new FormClose(form_FormClosed);
// add it to the stack
stack.Add(FormType.Name);
Monitor.Exit(this);
}
public StackForm Preload(Type FormType) {
StackForm form = (StackForm)Activator.CreateInstance(FormType);
// get data on a separate thread
form.LoadData();
// build the form
form.InitializeComponent();
// wait for the data thread to finish
form.threadRunning.WaitOne();
// now populate the controls with any retrieved data
form.Populate();
form.MinimizeBox = false; // required to get close event on PPC!
// add it to the cache
List.Add(form);
return form;
}
public void Pop(uint FormsToPop) {
if(stack.Count <= FormsToPop) {
throw new Exception("You cannot Pop the entire stack!");
}
else {
// remove from stack but not cache
for(int i = 0 ; i < FormsToPop ; i++) {
stack.RemoveAt(stack.Count - 1);
}
foreach(StackForm sf in List) {
// find the last form in the stack
if(sf.GetType().Name.Equals(stack[stack.Count - 1])) {
// make it visible
sf.Visible = true;
}
}
}
}
private void form_FormClosed() {
Pop(1);
}
public override string ToString() {
string message = "There are " + List.Count.ToString() + " forms cached\r\n";
message += "Stack contents:";
for(int i = stack.Count - 1 ; i >= 0 ; i--) {
message += "\r\n" + stack[i].ToString();
}
return message;
}
}
}
Run()
方法在应用程序运行时不断调用Application.DoEvents()
。我发现很难相信这对应用程序来说是件好事。我很想听到有关此事的其他意见。感谢。
答案 0 :(得分:1)
首先,您需要了解WinForms应用程序的工作原理。在Application.Run调用的深处,是一段代码,通常被称为消息泵。这是一个无限循环,调用GetMessage,TranslateMessage和DispatchMessage。实质上,Application.DoEvents调用该循环的一次循环。您正在查看的DoEvents循环只是执行此操作。
现在为什么,甚至需要这个电话,我不能诚实地说。这是非常糟糕的,因为我编写了代码,但在我的辩护中,这段代码已经差不多十年了,我几乎不记得上周我做了什么。
如果删除循环,会发生什么?我没有看到任何表明你会得到绘图工件或绘制失败的东西(这是添加调用的典型原因),但是这段代码也写成了aganst CF 1.0,所以很可能已经克服了运行时限制。
对于它的价值,我revisited and rewrote the code in 2009并且重写没有循环(或者甚至是Run方法)。
顺便说一下,我看到Push中有一个bug。 foreach循环有return
而没有执行Monitor.Exit。我可能会重写该方法以使用lock
或finally
块来调用Monitor.Exit。