Telling stories. Net commissioned: a c # bedtime story (the story of Peter)

Source: Internet
Author: User

Once upon a time, in a strange land in the south, Peter was a worker, who was very diligent and he was always obedient to his boss. However, his boss is a mean person. He never trusts others and insists that he know his work progress at any time to prevent him from being lazy. But Peter didn't want his boss to stay in his office and stare at him, so he made a promise to the boss: anytime, as long as I make some progress in my work, I will let you know in time. Peter periodically uses the "reference with type" (originally: "typed reference", that is, delegate ??) "Callback" is implemented by his boss as follows:

Class worker {
Public void advise (boss) {_ boss = boss ;}
Public void dowork (){
Console. writeline ("Work: Start of work ");
If (_ boss! = NULL) _ boss. workstarted ();

Console. writeline ("Work: Work in Progress ");
If (_ boss! = NULL) _ boss. workprogressing ();

console. writeline ("job: finished");
If (_ boss! = NULL) {
int grade = _ boss. workcompleted ();
console. writeline ("worker's work score =" + grade);
}< br> private boss _ boss;
}

Class boss {
Public void workstarted () {/* The boss does not care. */}
Public void workprogressing () {/* The boss does not care. */}
Public int workcompleted (){
Console. writeline ("Almost time !");
Return 2;/* Total score: 10 */
}
}

Class universe {
Static void main (){
Worker Peter = new worker ();
Boss = new boss ();
Peter. Advise (boss );
Peter. dowork ();

Console. writeline ("Main: worker finished ");
Console. Readline ();
}
}

Interface
Now, Peter has become a special person. He can not only tolerate stingy bosses, but also have a close relationship with the universe around him, so that he thinks the universe is also interested in his progress. Unfortunately, he must also add a special callback function advise to the universe to report the progress to both his boss and the universe. Peter wants to separate the list of potential notifications from the implementation methods of these notifications, so he decided to separate the methods into an interface:

Interface iworkerevents {
Void workstarted ();
Void workprogressing ();
Int workcompleted ();
}

Class worker {
Public void advise (iworkerevents events) {_ Events = events ;}
Public void dowork (){
Console. writeline ("Work: Start of work ");
If (_ events! = NULL) _ Events. workstarted ();

Console. writeline ("Work: Work in Progress ");
If (_ events! = NULL) _ Events. workprogressing ();

Console. writeline ("Work: finished "");
If (_ events! = NULL ){
Int grade = _ Events. workcompleted ();

Console. writeline ("Worker's work score =" + grade );
}
}
Private iworkerevents _ events;
}

Class BOSS: iworkerevents {
Public void workstarted () {/* The boss does not care. */}
Public void workprogressing () {/* The boss does not care. */}
Public int workcompleted (){
Console. writeline ("Almost time !");
Return 3;/* Total score: 10 */
}
}

Delegate
Unfortunately, Whenever Peter is busy communicating with his boss through the implementation of interfaces, there is no chance to notify the universe in time. At least he should ignore the reference from his boss in the distance, so that other objects implementing iworkerevents can get his work report. ("At least he 'd been acted the reference of his boss far away from him so that others who implemented the iworkerevents interface cocould be notified of his work SS, I don't understand what it means)

His boss complained a lot. "Peter !" His boss shouted, "Why are you bothering me at the beginning of your work ?! I don't care about these events. You not only forced me to implement these methods, but also wasted my precious work time to handle your events, especially when I went out! Can you leave me alone ?"

Peter realized that although the interface is useful in many cases, the "granularity" is not good enough when used as an event. He wanted to notify others only when they wanted them, so he decided to separate the interface method into a separate delegate, each delegate is like a small interface method:

Delegate void workstarted ();
Delegate void workprogressing ();
Delegate int workcompleted ();

Class worker {
Public void dowork (){
Console. writeline ("Work: Start of work ");
If (started! = NULL) started ();

Console. writeline ("Work: Work in Progress ");
If (progressing! = NULL) progressing ();

Console. writeline ("Work: finished "");
If (completed! = NULL ){
Int grade = completed ();
Console. writeline ("Worker's work score =" + grade );
}
}
Public workstarted started;
Public workprogressing progressing;
Public workcompleted completed;
}

Class boss {
Public int workcompleted (){
Console. writeline ("better ...");
Return 4;/* Total score: 10 */
}
}

Class universe {
Static void main (){
Worker Peter = new worker ();
Boss = new boss ();
Peter. Completed = new workcompleted (boss. workcompleted );
Peter. dowork ();

Console. writeline ("Main: worker finished ");
Console. Readline ();
}
}

Static listener
In this way, Peter will no longer bother his boss with what his boss doesn't want, but he hasn't put the universe into his listener list yet. Because the universe is an entity that contains everything, it seems that it is not suitable for the use of instance methods (imagine how much resources it will take to instantiate a "Universe .....), So Peter needs to be able to hook up the static delegate, which supports this well:

Class universe {
Static void workerstartedwork (){
Console. writeline ("universe notices worker starting work ");
}

Static int workercompletedwork (){
Console. writeline ("universe pleased with worker's work ");
Return 7;
}

Static void main (){
Worker Peter = new worker ();
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: worker finished ");
Console. Readline ();
}
}

 

Event
Unfortunately, the universe is too busy, and it is not used to paying attention to the individual in it at any time. It can replace boss Peter's delegate with its own delegate. This is an unconscious side effect of making Peter's worker class's delegate field public. Similarly, if Peter's boss is impatient, he can decide to inspire Peter's delegation by himself (really a rude boss ):

// Peter's boss taking matters into his own hands
If (Peter. completed! = NULL) Peter. Completed ();

Peter doesn't want this to happen. He realizes that he needs to provide "Registration" and "anti-Registration" functions for each delegate so that the listener can add and remove the delegate by himself, but at the same time, the entire list cannot be cleared and Peter's events cannot be triggered at will. Peter didn't implement these functions by himself. Instead, he used the event keyword to let the C # compiler build these methods for him:

Class worker {
...
Public event workstarted started;
Public event workprogressing progressing;
Public event workcompleted completed;
}

Peter knows that the event keyword encapsulates a property outside the delegate and only allows C # customers to add and remove the property through the + = and-= operators, forces his boss and universe to use the event correctly.

Static void main (){
Worker Peter = new worker ();
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: worker finished ");
Console. Readline ();
}

"Harvest" all results
At this moment, Peter finally gave a sigh of relief. He successfully met the needs of all the listeners and avoided the tight coupling with specific implementations. But he noticed that his boss and universe scored points for their work, but he only received one score. In the face of multiple listeners, he wants to "get" all the results, so he goes deep into the agent, polls the listener list, and calls them one by one:

Public void dowork (){
...
Console. writeline ("Work: finished "");
If (completed! = NULL ){
Foreach (workcompleted WC in completed. getinvocationlist ()){
Int grade = WC ();
Console. writeline ("Worker's work score =" + grade );
}
}
}
 
 

Asynchronous notification: inspire & forget
At the same time, his boss and the universe are still busy dealing with other things. That is to say, the time they spent scoring Peter has become very long:

Class boss {
Public int workcompleted (){
System. Threading. thread. Sleep (3000 );
Console. writeline ("better..."); return 6;/* Total score: 10 */
}
}

Class universe {
Static int workercompletedwork (){
System. Threading. thread. Sleep (4000 );
Console. writeline ("universe is pleased with worker's work ");
Return 7;
}
...
}

Unfortunately, each time Peter notifies a listener, he has to wait for it to rate himself. Now these notifications have consumed too many work events. So he decided to forget the score and just asynchronously stimulate the event:

Public void dowork (){
...
Console. writeline ("Work: finished "");
If (completed! = NULL ){
Foreach (workcompleted WC in completed. getinvocationlist ())
{
WC. begininvoke (null, null );
}
}
}

Asynchronous notification: Round Robin
This allows Peter to notify his listener and immediately return to work so that the thread pool of the process can call these agents. As time passes, Peter finds that he has lost his work feedback. He knows that listening to others' praise is just as important as working hard, so he asynchronously inspires events, but periodically polls, obtain available scores.

Public void dowork () {
...
console. writeline ("job: finished" ");
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 ("worker's work score =" + grade);
}< BR >}

Asynchronous notification: Delegate
Unfortunately, Peter came back to a situation he wanted to avoid from the beginning. For example, the boss stood behind and stared at his work. Therefore, he decided to use his delegate as the notification of the asynchronous delegate he called, so that he could immediately return to work, but he could still be notified after someone else scores his work:

Public void dowork (){
...
Console. writeline ("Work: finished "");
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 ("Worker's work score =" + grade );
}

Happiness in the universe
Peter, his boss, and the universe finally met. Peter's boss and universe can receive notifications of events they are interested in, reducing the burden of implementation and non-essential travel expenses ". Peter can notify them, no matter how long it takes them to return results from the target method, and asynchronously get their results. Peter knows that this is not ** very simple, because when he asynchronously fires an event, the method must be executed in another thread, and the notification of Peter's objective method completion is the same. However, Mike and Peter are good friends and he is very familiar with thread things and can provide guidance in this field.

They live happily forever ...... <End>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.