2011-03-13 2 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 루프는 단순히이 작업을 수행합니다.

왜 그 호출이 필요한지 나는 정직하게 말할 수 없다. 코드가으로 작성되었지만,이 코드는 거의 10 년이 넘었고, 지난 주에했던 일을 간신히 기억할 수 있습니다.

루프를 제거하면 어떻게됩니까? 드로잉 아티팩트 또는 드로잉 실패 (콜을 추가하는 일반적인 이유)가 있음을 나타내는 아무것도 보이지 않지만이 코드는 또한 CF 1.0을 작성했기 때문에 런타임 제한.

가치가 무엇인지, 나는 revisited and rewrote the code in 2009이고, 재 작성에는 루프 (또는 그 문제에 대한 실행 방법)가 없습니다.

현재, 내가보기에 푸시에 버그가 있습니다. foreach 루프는 Monitor.Exit을 수행하지 않고 return입니다. 아마도 lock 또는 finally 블록을 사용하여 Monitor.Exit를 호출하는 방법을 다시 작성해야합니다.

관련 문제