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