Anders Liu (lover_P)的.NET天空

传播知识基于掌握知识,但又高于掌握知识。我要做一个掌握很多知识的传播知识的人!

用户操作
[即时聊天] [发私信] [加为好友]
Anders LiuID:loverP
110531次访问,排名798好友0人,关注者5
loverP的文章
原创 35 篇
翻译 5 篇
转载 0 篇
评论 190 篇
Anders Liu的公告


我写的书


购买途径:
最近评论
kwlong2008:我是做网站建设的,来看看你的空间,不错,欢迎踩我的网站制作空间!
l763820708:有-在17号端口
txfast:这些话说的比较实际,其实说学习能力强只是一句空话,因为刚进公司,谁能够认可你的学习能力强,谁又能否定一个人的学习能力?
Wind_Eagle:想不到情人节还有心思写博客呀!不错,我有同感 !
heaso14:照着做了 还是有问题啊...

1>MSVCRT.lib(crtexew.obj) : error LNK2001: 无法解析的外部符号 _WinMain@16
1>C:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\a\PureC\Rele……
文章分类
收藏
    相册
    MVP Logo
    文章用图1
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 [连载] 用C#进行思考(三 之 前传)用委托实现回调收藏

    新一篇: [述评] 也说《代码大全2》 | 旧一篇: [连载] 用C#进行思考(侧注1.1)现实生活中的生产者和消费者实例

      前文提到过回调。也就是当发生不得不由生产者调用消费者时,不能直接使用方法调用,必须使用回调。

    (插:虽然在这里我对回调提出了新的定义,但实际上与传统意义上的回调并不冲突。试想一下Windows中的回调,基本上都是系统为我们提供了一写功能[生产者],而我们在调用这些功能时,又必须为其提供一个操作,以便其进行调用,这时才会产生回调。)

      在.NET中,使用委托实现回调。委托有两种方式——将委托作为参数传递、将委托作为类的域(Field)成员。前者就是这里要说的,很简单;而后者,放在下一篇文章再说,作为域成员的委托直接导致了事件的诞生。

      考虑在老板(消费者)和员工(生产者)之间,老板希望在员工做完工作后进行检查。

    // Boss.cs
    public class Boss
    {
        Employee m_anEmployee 
    = new Employee();

        
    public viod DispatchJob()
        
    {
            
    try  // 异常处理在大多数情况下是需要的,因为工作不一定成功
            {
                m_anEmployee.DoJob();
                m_check();  
    // 检查工作
                
    // 将“工作状态”改为“完成”
            }

            
    catch(Exception ex)
            
    {
                
    // 处理异常情况
                
    // 将“工作状态”改为“错误”
            }

        }


        
    private void m_check()
        
    {
            
    // 执行对工作的检查
        }

    }


    // Employee.cs
    public class Employee
    {
        
    public void DoJob()
        
    {
            
    // 完成工作,出错时抛异常
        }

    }

      在这里,作为消费者的老板,做了太多的事情(无论出于实际生活,还是出于在编程中的体验,都是不合理的)。因此这里也暴露出一种经验,就是当你发现你的一个类型,作为生产者的角色时,其实现太过简单,那么说明你的设计一定是有问题的。

      考虑这样一个问题,如果在使用Employee时,忘记作异常处理怎么办?忘记了调用check,没有检查工作怎么办?又或者不忘,那么每写一个用到了员工的类型或方法时,都要添加这样的代码,重复工作也是不能忍的。尤其是当DoJob方法要消耗大量时间时,每个调用都要在Boss中单独开启后台线程,工作量繁重且易出错。注意在这种方式下不能在DoJob中开启后台线程,否则就不能保证m_check方法是在DoJob完成后调用的。

      考虑使用回调。

    // Boss.cs
    public class Boss
    {
        Employee m_anEmployee 
    = new Employee();

        
    public viod DispatchJob()
        
    {
            JobFinishedCallback cb 
    = new JobFinishedCallback(m_check);
            m_anEmployee.DoJob(cb);  
    // 使用回调,简化了调用
        }


        
    private void m_check(JobState s)
        
    {
            
    if(s = JobState.Finished)
                
    // 进行具体的检查
            else
                
    // 处理错误
        }

    }


    // Employee.cs
    public delegate void JobFinishedCallback(JobState s);

    public enum JobState
    {
        Finised, Error
    }


    public class Employee
    {
        
    public void DoJob(JobFinishedCallback cb)
        
    {
            
    try  // 可以在DoJob内部处理错误
            {
                
    // 完成工作,出错时抛异常
                if(cb != null)
                    cb(JobState.Finished);
            }

            
    catch(Exception)
            
    {
                
    if(cb != null)
                    cb(JobState.Error);
            }

        }

    }

      现在,Boss的实现变得非常简单。如果需要添加后台线程,也只需在Employee中添加即可。甚至,还可以将多个方法链接到cb回调中(别忘了C#使用多播委托),用一系列方法来处理JobFinished这件事。(咦,事件的概念是不是冒出来了?且听下回分解。)

    发表于 @ 2006年09月10日 06:51:00|评论(loading...)|编辑

    新一篇: [述评] 也说《代码大全2》 | 旧一篇: [连载] 用C#进行思考(侧注1.1)现实生活中的生产者和消费者实例

    评论

    #Rock.fq 发表于2006-09-11 14:09:00  IP: 202.165.216.*
    怪不得是前转,下回一定是事件~
    #Rock.fq 发表于2006-09-11 14:10:00  IP: 202.165.216.*
    怪不得是前转,下回一定是事件~
    #Junior 发表于2006-09-12 19:26:00  IP: 124.254.34.*
    对委托还是不甚明了,只停留在此,我对程序的理解如下,如我说的洗衣机的那个例子:
    namespace MyDelegate
    {
    delegate void FixClothes();
    class Program
    {
    static void Main()
    {
    Person Junior = new Person();
    Junior.DoHomework();
    }
    }

    class Person
    {
    Washer myWasher;

    public Person()
    {
    myWasher = new Washer();
    }

    public void DoHomework()
    {
    Console.WriteLine("do homework");
    FixClothes fc = new FixClothes(this.SunCloth);
    myWasher.WashCloth(fc);
    }

    public void SunCloth()
    {
    Console.WriteLine("sun the clothes");
    }
    }

    class Washer
    {
    public void WashCloth(FixClothes fm)
    {
    Console.WriteLine("wash clothes");
    fm();
    }
    }
    }
    #Junior 发表于2006-09-12 19:31:00  IP: 124.254.34.*
    对委托的认识基本就到这了,还没有看事件,事件就更头大了。自己做了几个例子,都像这种类型的,消费者调生产者,生产者完成一件事后,消费者再处理这个事情,现在也就是对这个例子的语法清楚,不知以后该怎么做。
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © Anders Liu