成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

探討WinForm不同代碼的實現

開發 后端
本文將通過對不同方法的WinForm代碼進行對比,希望能對大家更好的了解WinForm有所幫助。

WinForm看上去有些深奧,在這里我們將探討WinForm二三事,希望通過以下的文字,能讓大家在開發過程中對WinForm有更深入的了解和認識。

在進入正文之前,想請大家先欣賞下面兩段代碼:

  1. //這是一個控制臺程序,請先添加System.Windows.Form.dll的引用   
  2. using System.Windows.Form;       
  3. public class ConsoleApplicationShowDialog    
  4. {     
  5.    static void Main()    
  6.     {     
  7.         Form frm = new Form();    
  8.        frm.ShowDialog();    
  9.   }    
  10.  }    

兩個代碼片段都是控制臺程序(編譯的時候,請選擇ConsoleApplication類型編譯)。這兩段程序***的區別就在于顯示窗體的時候***個使用ShowDialog(就是所謂的模態窗體),第二個使用Show(也就是所謂的非模態窗體)。

經過測試我們發現,使用Show顯示出來的窗體一顯示就死在那里了,不響應用戶的輸入,如果你在窗體上放一個按鈕,甚至發現按鈕都無法顯示,點擊也無任何響應。而是用ShowDialog顯示出來的窗體卻不一樣,可以響應用戶的輸入。這是什么原因呢?

為了找到問題的根源,我們來看看Show方法和ShowDialog方法實現的區別。Show方法是在Control里定義的,Form間接的派生自Control類(看起來這里是一個組合模式哦),Show方法代碼:

  1. public void Show()    
  2.  {     
  3.      this.Visible = true;    
  4.  }  

Show方法的代碼相當的簡單,做的工作僅僅就是將窗體顯示出來,那前面第二段代碼應該與下面的代碼作用是一樣的:

  1. //這是一個控制臺程序,請先添加System.Windows.Form.dll的引用     
  2.  using System.Windows.Form;   
  3. public class ConsoleApplicationShow     
  4. {    
  5.   static void Main()   
  6.     {     
  7.         Form frm = new Form();    
  8.     frm.Visible = true;   
  9.   }    

現在再來看看ShowDialog方法,ShowDialog方法有些復雜,但是在這百來行代碼中,應該有一條你很熟悉:

  1. public DialogResult ShowDialog(IWin32Window owner)     
  2. {     
  3.     //...省略     
  4.      Application.RunDialog(this);     
  5.     //...省略     
  6.  } 

哦,這行代碼跟我們千千萬萬個WinForm程序的啟動部分相當類似:

  1. public class Program     
  2. {     
  3.    static void Main()     
  4.      {    
  5.          Form frm = new Form();     
  6.          Application.Run(frm);    
  7.     }     
  8. }  

MSDN對Application.Run的說明是:

Begins running a standard application message loop on the current thread, and makes the specified form visible.在當前的線程上啟動一個標準的應用程序“消息循環”,并且顯示指定的窗體,下面是Application.Run的代碼:

  1. public static void Run(Form mainForm){    
  2. ThreadContext.FromCurrent().RunMessageLoop(-1, new   
  3. ApplicationContext(mainForm));  
  4. }  

哦?什么是消息循環?如果你是直接進入.Net開發的,沒有經過Win32時代的洗禮,那可能對這個消息循環并不是很清楚,在你眼里只有注冊事件,處理事件。雖然.Net通過封裝,簡化了消息循環這種處理用戶點擊等事件的編程模型,但是.Net底下還是Win32,有的時候我們還是得了解一下,對理解有些問題可能有幫助(后面會提到)。

消息循環(Message Loop)

說Application.Run啟動一個消息循環,那么什么是消息循環呢?看下面的代碼:

  1. MSG msg;   
  2. while(GetMessage(&msg,NULL,0,0)){   
  3.    TranslateMessage(&msg);      
  4. DispatchMessage(&msg);  

這是一段幾乎所有使用Win32 API編寫Windows Application的程序里都有的代碼。這就是一個消息循環。你不需要透徹的理解上面這段代碼,你只需要了解這么一個意思:

Windows為每個Windows程序都維護了一個消息隊列,當有用戶輸入事件的時候,Windows就把這個事件轉換為一個稱之為“消息”的東東(也就是上面代碼中的MSG結構),在這個消息里包含有一些信息,比如鼠標點擊的點啊,消息的類型啊等等。而上面的while循環中的GetMessage方法就是不斷的從這個消息隊列里取消息出來,然后處理,這樣窗體就能響應用戶的輸入了。

通過上面的討論,我們現在大概明白了為啥Show和ShowDialog區別這么大呢,原來ShowDialog啟動了一個消息循環,這樣用ShowDialog顯示出來的窗體就能響應用戶的輸入事件了,而Show僅僅是設置一下窗體的Visible屬性,并沒有啟動一個消息循環,使用Show顯示出來的窗體也就無法響應用戶的輸入事件了,也就是死在那里了。

上面說,GetMessage取出消息,然后處理,那在哪兒處理呢?在Win32程序中我們還可以看到這樣的片段:

  1. LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM   
  2. wParam,LPARAM lParam){   
  3.    switch(message)    {        
  4.   case WM_CREATE:            //處理窗體創建事件                
  5.  return 0;          
  6. case WM_PAINT:            //處理窗體繪制事件              
  7. return 0;                //更多事件,比如按鈕點擊等      
  8. }  

啊,好丑陋的處理方式。原來是根據message的類型,做出不同的處理,而Windows定義了一大堆WM_開頭的東東。可我們可愛的.Net,WinForm里面優美的事件處理模型就是基于這個之上的,通過上面的代碼,和你在.Net里使用事件的感觸你是否能想象出.Net是如何封裝這個過程的?

WinForm中的消息處理

實際上在.Net的WinForm中,消息處理的影子還是存在的,并沒有消失得無影無蹤,在Form中還有這么一個protected的方法:

  1. protected override void WndProc(ref Message m){   
  2.    switch (m.Msg)    {          
  3. case 0x10://......          
  4. case 0x11:        //....     
  5.  }      
  6. base.WndProc(ref m);} 

哦,原來與Win32里面的那個一模一樣。實際上通過重寫這個方法我們可以實現一些正常做法難以實現的東東。

為什么耗時操作要異步

談了這么多,我們來談一點我們身邊的事情。你應該碰到過這樣一個場景:編寫一個程序,點擊一個按鈕之后要做一個比較耗時的操作,比如要更新一大批數據到數據庫,這個時候程序就像本文開頭那個程序一樣,死掉了。用戶不管怎么點擊,程序變成灰色,標題欄上還顯示一個“沒有響應”,有的程序甚至連個提示都不給,用戶以為真的死掉了,氣急敗壞的啪嚓一下把程序關了,耗時操作進行到一半就這樣被無情終止。這是為什么呢?

通過前面的討論,我們知道,響應用戶的輸入就是靠消息循環,而消息循環就是在當前的線程上,也就是我們所謂的那個UI線程,如果一個耗時操作也同在UI線程上,那么消息循環就“卡著”了,也就無法處理后續的消息,程序也就假死了。

那我們如何處理這種耗時操作呢?當然就是將這個耗時操作放到另外一個線程中,不占用UI線程,讓消息循環得以繼續的進行下去。

原文標題:WinForm二三事

鏈接:http://www.cnblogs.com/yuyijq/archive/2009/11/04/1595775.html

責任編輯:彭凡 來源: 博客園
相關推薦

2019-06-03 09:00:25

Kubernetes部署金絲雀版本

2024-08-20 08:05:14

WinformWndProc?Windows

2024-04-19 00:47:07

RabbitMQ消息機制

2010-12-22 11:19:09

Java字節代碼

2009-12-01 16:34:21

PHP表單

2009-12-02 19:42:24

PHP頁面自動跳轉

2024-10-10 08:32:28

Redis高并發Lua

2024-05-11 08:20:23

2009-11-23 10:31:25

PHP使用JSON

2009-11-30 18:59:52

PHP數組排序

2010-01-04 17:29:00

Silverlight

2010-02-03 10:50:33

C++多態

2009-11-30 17:49:51

PHP函數preg_s

2010-01-20 09:14:49

C語言模塊化

2021-01-05 13:23:39

數據中心數據中心節能碳中和

2009-09-03 17:01:04

C#回車切換焦點

2022-02-21 08:18:38

option編程模式

2024-10-15 16:01:19

SpringBoot緩存預熱

2009-09-01 10:35:59

C# WinForm控

2009-12-11 13:25:01

PHP頁面跳轉
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产成人精品一区二区在线 | 欧美福利视频一区 | 在线观看免费毛片 | 亚洲视频欧美视频 | 黄色一级大片在线观看 | 中文av网站 | 免费国产一区二区 | 99免费在线| 免费v片 | av在线成人 | 欧美成人一级视频 | 在线欧美亚洲 | 91黄在线观看 | 亚洲成人免费在线 | 欧美一区二区三区电影 | 在线播放中文字幕 | 成人日批视频 | 日日操日日干 | 国产精品久久久久久久久久软件 | 中文字幕在线看 | 成人免费淫片aa视频免费 | 国产精品久久久久久久久免费丝袜 | 五月激情综合 | 国产色在线| 亚洲免费在线 | 欧美日韩国产精品一区二区 | 九九九视频精品 | 日韩电影在线一区 | 色综合久 | 亚洲国产成人精品久久 | 日韩欧美视频在线 | 久久精品综合 | 成人亚洲| 欧美国产精品一区二区三区 | h片在线看| 日韩免费视频 | 亚洲精品美女视频 | 国产高清精品在线 | 亚洲高清在线播放 | 午夜免费在线电影 | 在线观看国产 |