c#

位置:IT落伍者 >> c# >> 浏览文章

NET委托:一个关于C#的睡前故事[3]


发布日期:2019年10月15日
 
NET委托:一个关于C#的睡前故事[3]
事件 不幸的是宇宙太忙了也不习惯时刻关注它里面的个体它可以用自己的委托替换了彼得老板的委托这是把彼得的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);

}

宇宙中的幸福

彼得他的老板和宇宙最终都满足了彼得的老板和宇宙可以收到他们感兴趣的事件通知减少了实现的负担和非必需的往返差旅费彼得可以通知他们而不管他们要花多长时间来从目的方法中返回同时又可以异步地得到他的结果彼得知道这并不*十分*简单因为当他异步激发事件时方法要在另外一个线程中执行彼得的目的方法完成的通知也是一样的道理但是迈克和彼得是好朋友他很熟悉线程的事情可以在这个领域提供指导

他们永远幸福地生活下去……

[] [] []

               

上一篇:NET委托:一个关于C#的睡前故事[2]

下一篇:NET委托:一个关于C#的睡前故事[1]