程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C# 2.0:使用匿名方法、迭代程序和局部類來創建優雅的代碼(13)

C# 2.0:使用匿名方法、迭代程序和局部類來創建優雅的代碼(13)

編輯:關於C語言

Windows 窗體依賴於基本的 Win32 消息。因此,它繼承了典型的 Windows 編程要求:只有創建窗口的線程可以處理它的消息。在 .Net 框架 2.0 中,調用錯誤的線程總會觸發一個 Windows 窗體方面的異常。因此,當在另一個 線程中調用窗體或控件時,必須將該調用封送到正確的所屬線程中。Windows 窗 體有內置的支持,可以用來擺脫這個困境,方法是用 Control 基類實現 ISynchronizeInvoke 接口,其定義如下:

public interface ISynchronizeInvoke
{
  bool InvokeRequired {get;}
  IAsyncResult BeginInvoke(Delegate method,object[] args);
  object EndInvoke(IAsyncResult result);
  object Invoke(Delegate method,object[] args);
}

Invoke 方法接受針對所屬線程中的 方法的委托,並且將調用從正在調用的線程封送到該線程。因為您可能並不總是 知道自己是否真的在正確的線程中執行,所以通過使用 InvokeRequired 屬性, 您可以進行查詢,從而弄清楚是否需要調用 Invoke 方法。問題是,使用 ISynchronizeInvoke 將會大大增加編程模型的復雜性,因此較好的方法常常是將 帶有 ISynchronizeInvoke 接口的交互封裝在控件或窗體中,它們會自動地按需 使用 ISynchronizeInvoke。

例如,為了替代公開 Text 屬性的 Label 控 件,您可以定義從 Label 派生的 SafeLabel 控件,如圖 10 所示。SafeLabel 重寫了其基類的 Text 屬性。在其 get 和 set 中,它檢查 Invoke 是否是必需 的。如果是這樣,則它需要使用一個委托來訪問此屬性。該實現僅僅調用了基類 屬性的實現,不過是在正確的線程上。因為 SafeLabel 只定義這些方法,所以它 們可以通過委托進行調用,它們是匿名方法很好的候選者。SafeLabel 傳遞這樣 的委托,以便將匿名方法作為其 Text 屬性的安全實現包裝到 Invoke 方法中。

委托推理

C# 編譯器從匿名方法指派推理哪個委托類型將要實例化的能 力是一個非常重要的功能。實際上,它還提供了另一個叫做委托推理的 C# 2.0 功能。委托推理允許直接給委托變量指派方法名,而不需要先使用委托對象包裝 它。例如下面的 C# 1.1 代碼:

class SomeClass
{
  delegate void SomeDelegate();
  public void InvokeMethod()
  {
   SomeDelegate del = new SomeDelegate(SomeMethod);
   del();
  }
  void SomeMethod()
  {...}
}

現在,您可以編寫下面的代碼來代替前面的代碼片斷:

class SomeClass
{
  delegate void SomeDelegate ();
  public void InvokeMethod()
  {
    SomeDelegate del = SomeMethod;
   del();
  }
  void SomeMethod()
  {...}
}

當將一個方法名指派給委托時, 編譯器首先推理該委托的類型。然後,編譯器根據此名稱檢驗是否存在一個方法 ,並且它的簽名是否與推理的委托類型相匹配。最後,編譯器創建一個推理委托 類型的新對象,以便包裝此方法,並將其指派給該委托。如果該類型是一個具體 的委托類型(即除了抽象類型 Delegate 之外的其他類型),則編譯器只能推理 委托類型。委托推理的確是一個非常有用的功能,它可以使代碼變得簡練而優雅 。

我相信,作為 C# 2.0 中的慣例,您會使用委托推理,而不是以前的委 托實例化方法。例如,下面的代碼說明了如何在不顯式地創建一個 ThreadStart 委托的情況下啟動一個新的線程:

public class MyClass
{
  void ThreadMethod()
  {...}
  public void LauchThread()
  {
   Thread workerThread = new Thread (ThreadMethod);
   workerThread.Start();
  }
}

當啟動一個異步調用並提供一個完整的回調方法時,可以使用一對委 托推理,如圖 11 所示。首先,指定異步調用的方法名來異步調用一個匹配的委 托。然後調用 BeginInvoke,提供完整的回調方法名而不是 AsyncCallback 類型 的委托。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved