.Net学习爱好者的温馨家园

.Net互动平台

导航

关于如何使用自定义的结束消息循环的方式 (转载)

其实这个问题对于高手来说可能是很简单的,因为真正的实现过程并不复杂,实际上涉及到的代码也并不多,但是在没有搞清楚在.net下系统如何退出线程之前,这个问题还是困扰了我这个菜鸟很久的。

     感觉上对于一个简单的单线程的winform程序来说,好像点击了主Form的close,主线程就自动退出了。但是它是如何退出的呢?

     在查阅了MSDN和SDK之后,这个问题逐步的明朗了。

     首先一定要清楚一件事,那就是当主窗体初始化完成后当前线程在做什么,其实是在等待(等待处理新的消息):
处理消息队列中的新消息 Application.Run();

    这一点还是很好理解的,可是如何定义退出呢?谁来负责消息循环的退出(即结束当前线程)呢?其实,Application.Run()这个方法是和另外一个类的实例配合使用的---ApplicationContext类。SDK中对这个类的解释是:指定有关应用程序线程的上下文信息。乍一听,很是迷惑。可是看过SDK提供的例子思路就清晰了很多。我对代码进行了精简,只留下了足以说明问题的部分。

ApplicationContext的使用using System;
using System.Windows .Forms ;
using System.Drawing;
using System.ComponentModel ;

namespace ApplicationContextTest
{
     public class AppForm1 : System.Windows .Forms .Form
     {
          public AppForm1()
         {
               this.Size = new Size (200,200);
              this.Text = "AppForm1";
         }
 }

 public class Test : ApplicationContext
 {
      private AppForm1 form1;
      private Test()
      {
         form1 = new AppForm1 ();
         form1.Closed += new EventHandler(OnFormClosed);

         form1.Show ();
      }
       public void OnFormClosed(object sender, EventArgs e)
       {
            ApplicationContext appContext = new ApplicationContext (form1);
            appContext.ExitThread ();
        }

  [STAThread]   
  public static void Main()
  {
        Test test = new Test ();
        Application.Run (test);
  }
 }
}

   
    我们通过上面的代码可以看到,实际上Run()方法是有参数的,也就是所谓的线程的上下文,它的参数就是ApplicationContext类或者它的派生类。通常情况下,如果我们没有自定义ApplicationContext的派生类的话,那么默认的线程上下文就是.net提供的ApplicationContext类本身。这时候,消息循环是通过主Form的OnClosed事件来结束的(果不出我之所料,不过好像太简单了,地球人都知道... ...)。需要特别说明的一点是,其实ApplicationContext只是负责监听(监听OnClosed事件),真正负责退出消息循环的还是Application类自己。

    但是在上面的代码中我们通过构建自己的ApplicationContext类的实例(我习惯把class A的派生类叫做"自己的A类",大家明白即可),我们在类的内部重新定义了如何推出消息循环(其实就是按自己的需要重新定义退出消息循环的条件),可以看到,消息循环的退出不再是由于发生了主Fomr的OnClosed事件,而是子窗体的OnClosed事件(这里给出的条件似乎不是很典型,我们当然也可以响应其他的系统事件,来结束当前线程中的消息循环)。
    这样一来,我们就可以实现自定义当前线程的消息循环的退出条件了。我感觉这样做在某些时候应该还是很有意义的,比如对于一个应用程序,它的主窗体并没有实际的意义,真正有意义的是所有的子窗体,换句话说当所有的子窗体都close掉以后,应用程序结束。这个时候主Form的close对于我们是没有意义的,我们可以在用户点击了主Form的close之后,通过CancelEventArgs 的实例e来取消主程序的结束,并隐藏主窗体,以防止用户对主窗体进行不必要的操作。
主窗体的处理private void MainForm_OnClosed(object sender, CancelEventArgs e)
{
    e.Cancel  =  true;
    ((Form)sender).Hide();
}
    当然了,对于主窗体来说如果在某些时候还需要使用的话,干脆做成系统托盘会更好一些。
    这时候,我们只需要在我们从ApplicationContext类派生出来的类中定义消息推出的条件就可以了,比如条件是子窗体的计数器为零则程序退出。(可一定要保证在程序启动的时候至少有一个子窗体呦)
    最后不要忘了在程序中将派生类进行实例化,并且将实例对象作为Run()方法的参数。

posted on 2006-11-30 17:21  Xt Idt  阅读(547)  评论(1编辑  收藏  举报