熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

NET委托:一個關於C#的睡前故事[3]

2013-11-13 12:15:52  來源: .NET編程 
    事件 不幸的是宇宙太忙了也不習慣時刻關注它裡面的個體它可以用自己的委托替換了彼得老板的委托這是把彼得的Worker類的的委托字段做成public的一個無意識的副作用同樣如果彼得的老板不耐煩了也可以決定自己來激發彼得的委托(真是一個粗魯的老板)

// Peters boss taking matters into his own hands
if( petercompleted != null ) petercompleted();


  彼得不想讓這些事發生他意識到需要給每個委托提供注冊反注冊功能這樣監聽者就可以自己添加和移除委托但同時又不能清空整個列表也不能隨意激發彼得的事件了彼得並沒有來自己實現這些功能相反他使用了event關鍵字讓C#編譯器為他構建這些方法

class Worker {
 
 public event WorkStarted started;
 public event WorkProgressing progressing;
 public event WorkCompleted completed;
}


  彼得知道event關鍵字在委托的外邊包裝了一個property僅讓C#客戶通過+= 和 =操作符來添加和移除強迫他的老板和宇宙正確地使用事件

static void Main() {
 Worker peter = new Worker();
 Boss boss = new Boss();
 petercompleted += new WorkCompleted(bossWorkCompleted);
 peterstarted += new WorkStarted(UniverseWorkerStartedWork);
 petercompleted += new WorkCompleted(UniverseWorkerCompletedWork);
 peterDoWork();

 ConsoleWriteLine(Main: 工人工作完成);
 ConsoleReadLine();
}


  收獲所有結果

  到這時彼得終於可以送一口氣了他成功地滿足了所有監聽者的需求同時避免了與特定實現的緊耦合但是他注意到他的老板和宇宙都為它的工作打了分但是他僅僅接收了一個分數面對多個監聽者他想要收獲所有的結果於是他深入到代理裡面輪詢監聽者列表手工一個個調用

public void DoWork() {
 
 ConsoleWriteLine(工作: 工作完成);
 if( completed != null ) {
  foreach( WorkCompleted wc in completedGetInvocationList() ) {
   int grade = wc();
   ConsoleWriteLine(工人的工作得分= + grade);
  }
 }
}


  異步通知激發 & 忘掉

  同時他的老板和宇宙還要忙於處理其他事情也就是說他們給彼得打分所花費的事件變得非常長

class Boss {
 public int WorkCompleted() {
  SystemThreadingThreadSleep();
  ConsoleWriteLine(Better); return ; /* 總分為 */
 }
}

class Universe {
 static int WorkerCompletedWork() {
  SystemThreadingThreadSleep();
  ConsoleWriteLine(Universe is pleased with workers work);
  return ;
 }
 
}


  很不幸彼得每次通知一個監聽者後必須等待它給自己打分現在這些通知花費了他太多的工作事件於是他決定忘掉分數僅僅異步激發事件

public void DoWork() {
 
 ConsoleWriteLine(工作: 工作完成);
 if( completed != null ) {
  foreach( WorkCompleted wc in completedGetInvocationList() )
  {
   wcBeginInvoke(null null);
  }
 }
}


  異步通知輪詢

  這使得彼得可以通知他的監聽者然後立即返回工作讓進程的線程池來調用這些代理隨著時間的過去彼得發現他丟失了他工作的反饋他知道聽取別人的贊揚和努力工作一樣重要於是他異步激發事件但是周期性地輪詢取得可用的分數

public void DoWork() {
 
 ConsoleWriteLine(工作: 工作完成);
 if( completed != null ) {
  foreach( WorkCompleted wc in completedGetInvocationList() ) {
   IAsyncResult res = wcBeginInvoke(null null);
   while( !resIsCompleted ) SystemThreadingThreadSleep();
    int grade = wcEndInvoke(res);
    ConsoleWriteLine(工人的工作得分= + grade);
  }
 }
}


  異步通知委托

  不幸地彼得有回到了一開始就想避免的情況中來比如老板站在背後盯著他工作於是他決定使用自己的委托作為他調用的異步委托完成的通知讓他自己立即回到工作但是仍可以在別人給他的工作打分後得到通知

public void DoWork() {
 
 ConsoleWriteLine(工作: 工作完成);
 if( completed != null ) {
  foreach( WorkCompleted wc in completedGetInvocationList() ) {
   wcBeginInvoke(new AsyncCallback(WorkGraded) wc);
  }
 }
}

private void WorkGraded(IAsyncResult res) {
 WorkCompleted wc = (WorkCompleted)resAsyncState;
 int grade = wcEndInvoke(res);
 ConsoleWriteLine(工人的工作得分= + grade);
}


  宇宙中的幸福

  彼得他的老板和宇宙最終都滿足了彼得的老板和宇宙可以收到他們感興趣的事件通知減少了實現的負擔和非必需的往返差旅費彼得可以通知他們而不管他們要花多長時間來從目的方法中返回同時又可以異步地得到他的結果彼得知道這並不*十分*簡單因為當他異步激發事件時方法要在另外一個線程中執行彼得的目的方法完成的通知也是一樣的道理但是邁克和彼得是好朋友他很熟悉線程的事情可以在這個領域提供指導

  他們永遠幸福地生活下去……

[]  []  []  


From:http://tw.wingwit.com/Article/program/net/201311/15528.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.