事件 不幸的是
宇宙太忙了
也不習慣時刻關注它裡面的個體
它可以用自己的委托替換了彼得老板的委托
這是把彼得的Worker類的的委托字段做成public的一個無意識的副作用
同樣
如果彼得的老板不耐煩了
也可以決定自己來激發彼得的委托(真是一個粗魯的老板)
// Peter
s boss taking matters into his own hands
if( peter
completed != null ) peter
completed();
彼得不想讓這些事發生
他意識到需要給每個委托提供
注冊
和
反注冊
功能
這樣監聽者就可以自己添加和移除委托
但同時又不能清空整個列表也不能隨意激發彼得的事件了
彼得並沒有來自己實現這些功能
相反
他使用了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();
peter
completed += new WorkCompleted(boss
WorkCompleted);
peter
started += new WorkStarted(Universe
WorkerStartedWork);
peter
completed += new WorkCompleted(Universe
WorkerCompletedWork);
peter
DoWork();
Console
WriteLine(
Main: 工人工作完成
);
Console
ReadLine();
}
收獲
所有結果
到這時
彼得終於可以送一口氣了
他成功地滿足了所有監聽者的需求
同時避免了與特定實現的緊耦合
但是他注意到他的老板和宇宙都為它的工作打了分
但是他僅僅接收了一個分數
面對多個監聽者
他想要
收獲
所有的結果
於是他深入到代理裡面
輪詢監聽者列表
手工一個個調用
public void DoWork() {
Console
WriteLine(
工作: 工作完成
);
if( completed != null ) {
foreach( WorkCompleted wc in completed
GetInvocationList() ) {
int grade = wc();
Console
WriteLine(
工人的工作得分=
+ grade);
}
}
}
異步通知
激發 & 忘掉
同時
他的老板和宇宙還要忙於處理其他事情
也就是說他們給彼得打分所花費的事件變得非常長
class Boss {
public int WorkCompleted() {
System
Threading
Thread
Sleep(
);
Console
WriteLine(
Better
); return
; /* 總分為
*/
}
}
class Universe {
static int WorkerCompletedWork() {
System
Threading
Thread
Sleep(
);
Console
WriteLine(
Universe is pleased with worker
s work
);
return
;
}
}
很不幸
彼得每次通知一個監聽者後必須等待它給自己打分
現在這些通知花費了他太多的工作事件
於是他決定忘掉分數
僅僅異步激發事件
public void DoWork() {
Console
WriteLine(
工作: 工作完成
);
if( completed != null ) {
foreach( WorkCompleted wc in completed
GetInvocationList() )
{
wc
BeginInvoke(null
null);
}
}
}
異步通知
輪詢
這使得彼得可以通知他的監聽者
然後立即返回工作
讓進程的線程池來調用這些代理
隨著時間的過去
彼得發現他丟失了他工作的反饋
他知道聽取別人的贊揚和努力工作一樣重要
於是他異步激發事件
但是周期性地輪詢
取得可用的分數
public void DoWork() {
Console
WriteLine(
工作: 工作完成
);
if( completed != null ) {
foreach( WorkCompleted wc in completed
GetInvocationList() ) {
IAsyncResult res = wc
BeginInvoke(null
null);
while( !res
IsCompleted ) System
Threading
Thread
Sleep(
);
int grade = wc
EndInvoke(res);
Console
WriteLine(
工人的工作得分=
+ grade);
}
}
}
異步通知
委托
不幸地
彼得有回到了一開始就想避免的情況中來
比如
老板站在背後盯著他工作
於是
他決定使用自己的委托作為他調用的異步委托完成的通知
讓他自己立即回到工作
但是仍可以在別人給他的工作打分後得到通知
public void DoWork() {
Console
WriteLine(
工作: 工作完成
);
if( completed != null ) {
foreach( WorkCompleted wc in completed
GetInvocationList() ) {
wc
BeginInvoke(new AsyncCallback(WorkGraded)
wc);
}
}
}
private void WorkGraded(IAsyncResult res) {
WorkCompleted wc = (WorkCompleted)res
AsyncState;
int grade = wc
EndInvoke(res);
Console
WriteLine(
工人的工作得分=
+ grade);
}
宇宙中的幸福
彼得他的老板和宇宙最終都滿足了彼得的老板和宇宙可以收到他們感興趣的事件通知減少了實現的負擔和非必需的往返差旅費彼得可以通知他們而不管他們要花多長時間來從目的方法中返回同時又可以異步地得到他的結果彼得知道這並不*十分*簡單因為當他異步激發事件時方法要在另外一個線程中執行彼得的目的方法完成的通知也是一樣的道理但是邁克和彼得是好朋友他很熟悉線程的事情可以在這個領域提供指導
他們永遠幸福地生活下去……
[] [] []
From:http://tw.wingwit.com/Article/program/net/201311/15528.html