2011-03-13 49 views
1

我试图添加一个形式兑现模块为我的应用程序,我实现了这个MSDN示例:Form Stacking and CachingApplication.DoEvents()在应用程序运行时不断调用?

对于那些谁不能下载的样本,这是包含了一段代码,我指的类:

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()而应用捉迷藏。我很难相信这对于应用程序来说是件好事。我很乐意听到关于此的其他意见。谢谢。

回答

1

首先,您需要了解WinForms应用程序的一般工作方式。在Application.Run调用的深处深入一段代码通常被称为消息泵。这是一个调用GetMessage,TranslateMessage和DispatchMessage的无限循环。实质上,Application.DoEvents调用该循环的一次循环。你正在看的DoEvents循环只是做这个操作。

现在为什么,甚至需要这个电话我不能诚实地说。这很糟糕,因为我写了代码,但在我的防守中,这个代码已经有近十年的历史了,我几乎不记得上周我做了什么。

如果删除循环,会发生什么情况?我没有看到任何表明你会画图的人为因素或失败(这是添加调用的典型原因),但是这个代码也被写成了CF 1.0,所以它很可能已经被克服运行时限制。

对于它的价值,我revisited and rewrote the code in 2009和重写没有循环(或甚至运行方法)。

顺便说一句,我看到有一个Push错误。 foreach循环有一个return没有做一个Monitor.Exit。我可能会重写该方法使用lockfinally块来调用Monitor.Exit。

相关问题