找回密码
 立即注册

QQ登录

只需一步,快速开始

Carl

版主

49

主题

213

帖子

962

积分

版主

Rank: 7Rank: 7Rank: 7

积分
962

活字格认证微信认证勋章

QQ
Carl
版主   /  发表于:2009-12-9 16:41  /   查看:7673  /  回复:0
Post by "CoreyKou",2006-11-05, 11:55
-----------------------------------------------------

.Net中的Delegate对于实现异步调用的确方便和安全,但随着Delegate的使用,疑惑也是越来越多,想一探究竟以更好的使用:

Delegate如何实现异步调用?异步一定使用多线程吗?

欢迎大家积极投稿或转贴。扔块砖先。

.NET Delegates: Making Asynchronous Method Calls in the .NET Environment
http://msdn.microsoft.com/msdnmag/issues/01/08/Async/


Reply by "Razor",2006-11-06, 0:19
-----------------------------------------------------

CoreyKou:
Delegate如何实现异步调用?



简单说,当你声明并且编译了一个delegate,编译器会自动为你生成BeginInvoke和EndInvoke方法。当你调用delegate的BeginInvoke方法时,实际你要调用的方法(delegate只是一个桥梁)会被放到系统的一个队列里,等系统线程池中有了可用的线程以后,实际被调用的方法就会在线程池中的这个线程中执行。





更多请参考:http://msdn.microsoft.com/msdnmag/issues/04/01/BasicInstincts/


CoreyKou:

异步一定使用多线程吗?



是。

MSDN里关于异步编程模式的文档:

http://msdn2.microsoft.com/zh-cn/library/ms228969(VS.80).aspx (中文)


Reply by "dujid", 2006-11-06, 9:43
-----------------------------------------------------

我其实很不赞成使用 delegate 这种技术,尽管它确实有用武之地,但是这种技术破坏了面向对象的简单性。在面向对象中,我们遵循一切均为对象的原则,将变量作为属性,将方法作为行为,这一切看起来既简单又不失描述力,任何现实世界的事物,都可以用这基本的 3 种元素抽象到程序当中。

而 delegate,就好像一种行为自身变成了对象,你可以拿着它到处跑,随便赋给其他对象。例如 一个人 是一个对象,他会翻译英语的技能( translateEnglish() ) 是他的行为中的一个,如果这个方法变成了 delegate,那就意味着,你可以把这个技能赋给其他人,而其他人马上可以拥有这一技能。这一特性在现实生活中不可能发生。

程序的设计思想脱离了实际,很可能使程序员以技术思考作为出发点去想问题,从而将用户与业务抛到脑后,这并不是一件好事。


Reply by "Carl",2006-11-06, 10:15
-----------------------------------------------------

我赞成合理的使用delegate,并且认为这是一个伟大的发明。在我们的实践中,为了支持event这样的消息处理,必须得使用一种能够代替函数指针的技术。delegate是一个完美的解决方案,解决的函数指针的安全性问题,虽然它不是那么好理解,但是从实践来看确实是成功的设计。

这种思想在现实生活中也是有体现的。比如有个开关可以控制灯泡,delegate就是这个开关,他封装了控制灯泡的具体动作。拥有开关的人,可以随意控制相对应的灯泡的亮灭,而不是说谁有了这个开关,谁就有了电灯。

传统的面向对象已经不能满足我们在设计方面的巨大需要,才会有AOP这些新的设计思想的出现。其中的一个思想,就是把传统的方法,属性等等原来属于一个对象内部的东西,也用对象来表示。方法封装成对象就是delegate,至于属性,可以参考.NET 3.0中的DependencyProperty类型。相信在未来的设计里,所有的东西都会是对象。

补充一下,异步并不一定需要多线程,只要有一个调用队列就可以了。具体的例子可以参考.NET 3.0中的Dispatcher,在一个线程中可以实现异步调用。另外,CPU也是一个例子,一个运算器,人家不也实现了多进程切换嘛,并不是几个进程就要几个CPU。


Reply by "Razor", 2006-11-06, 12:17
-----------------------------------------------------

Carl:
我赞成合理的使用delegate



同意!



Carl:

补充一下,异步并不一定需要多线程,只要有一个调用队列就可以了。具体的例子可以参考.NET 3.0中的Dispatcher,在一个线程中可以实现异步调用。另外,CPU也是一个例子,一个运算器,人家不也实现了多进程切换嘛,并不是几个进程就要几个CPU。



是的,在目前的架构下,所谓的多任务和并行处理只是名词而已,实际上大家只是在操作系统的调度下轮流执行。

Dispatcher,嗯,还要好好看看。



Reply by "dujid", 2006-11-06, 15:01
-----------------------------------------------------


Carl:



这种思想在现实生活中也是有体现的。比如有个开关可以控制灯泡,delegate就是这个开关,他封装了控制灯泡的具体动作。拥有开关的人,可以随意控制相对应的灯泡的亮灭,而不是说谁有了这个开关,谁就有了电灯。



我认为这种思想在现实生活中是没有的。

> “他封装了控制灯泡的具体动作。”

这句话没有错。但动作是一种抽象存在的事物,在自然界中,它一定有一个宿主,即发出动作的源对象,在现实生活中你是不可能拿着这个抽象事物到处乱跑的。你能拿的,仅仅是对象。

>  拥有开关的人,可以随意控制相对应的灯泡的亮灭,而不是说谁有了这个开关,谁就有了电灯。

在你上句话中只能看出来那是一个“动作”,我很赞同。但这句话中说到拥有开关的人,我想开关并不等于动作,开关是具体的对象,不是只封装了开灯的动作,这里看来,你在举例中的抽象是混乱的。正确的是: 控制灯泡的动作是开关的一个行为,因此,开关是对象,人也是对象,即人只能得到开关,再通过开关的行为控制灯。我们用代码来试着描述这种抽象:

delegate void TurnOn(灯 light);


class 人 {

    TurnOn turnOn;

}


static int main(String args[]) {

   人 我 = new 人();

   灯 light = new 灯();


   我.turnOn = new delegate(灯 light) { light.powerOn = true; }

}

看这个例子,很显然,人被赋予了 turnOn 的技能,人可以开灯,假如也对一个对象橡皮赋予这样的delegate,那橡皮也有开灯的技能。这显然是不合理的。

Carl:
传统的面向对象已经不能满足我们在设计方面的巨大需要,才会有OAP这些新的设计思想的出现。其中的一个思想,就是把传统的方法,属性等等原来属于一个对象内部的东西,也用对象来表示。方法封装成对象就是delegate,至于属性,可以参考.NET 3.0中的DependencyProperty类型。相信在未来的设计里,所有的东西都会是对象。



严重不同意这句话,面向对象是一种思维方式,不是技术,用这种思想去分析事物,分析业务,把现实生活的东西用面向对象去抽象,并组织你的类。这个能力只是抽象程度的深浅不同,并不是自然界的事物不能用其来描述,或者不够去描述。也许是我才疏学浅,不懂什么叫 OAP,也许是 AOP,就算是 AOP, AOP 也是在面向对象的基础之上总结出来的一种以面向对象为基础的面向切面的思维方式,它本身就是面向对象,甚至说,如果没有面向对象,根本不会有 AOP。

同 AOP 相似的还有 IOC 等等,这是一度被炒得火热的设计思想,但以我认为,这些都是 OOP,只是把一种典型的 OO 思维方法抽取出来作为一种技术,并向大家推广,再包括一些典型的设计模式,它们核心,还是面向对象。

所以很多人认为面向对象过时了,或者传统的面向对象不能满足需要,AOP才诞生等等,这些都是对OOP的误解,而且没有透彻的掌握OO方法。以为学几个设计模式,写几个类就可以认为自己是面向对象了,更甚至是说面向对象不能满足需要, 但却有没有想过,我们是不是把面向对象真正的运用好了。

也许回帖言语有些刻薄,但我决不是针对你一个人,要不是讨论刚好说到这里,我还准备开一新帖,这些个人的主见早已想说出来,不对之处,还请多多指教。


Reply by "Carl",2006-11-06, 16:44
-----------------------------------------------------

问题到这里已经超越了技术的范畴。我并不想论证什么原则定理之类,只是想提出一些自己的看法,并不一定是成熟的或者正确的。

在我看来,程序设计的发展方向是尽可能的模拟客观世界。客观世界中,基本的组成部分是物质,那么面向对象编程所体现出的对象就是这样的物质。程序是由对象组成的,正如客观世界是由物质组成的。

但是,众所周知,我们的日常生活中会遇到一些非物质的概念,比如“开灯”这样的动作。既然客观世界中有这样的概念,我们的设计思想就得尽量包容这样的概念。不管你是用对象,还是别的什么东西,我们不能抹杀这种动作的存在。

我是唯物主义者,我认为客观世界既然可以全部用物质来描述,我们的程序就一定可以全部用对象来描述。现在我们所使用的面向对象编程中,仍旧有很多面向过程的成分,比如在一个方法的内部。但是我梦想有一天,程序设计完全就是把一堆对象合理的糅合在一起……(别问我,我也不知道到底该怎么揉,仅仅是一个梦)

回到上面的问题,dujid 的贴子中举了一个delegate的例子。我发表一下我的观点:

我仍旧认为delegate是很好的发明,但是这个例子明显不合理。火药是人类伟大的发明,但你用它来杀人就不对了。用delegate可以写出很糟糕的,不符合人类思维的程序,比如这个例子,但这不能说明delegate本身不合理。

那么什么样的例子是合理的?不用我说,大家也能举出一堆:event,ThreadStart,等等。这些delegate确实帮助我们很好的解决了问题。而像这个例子中那样,把delegate当作一个可以直接set的属性的设计,在我的编程生涯中还几乎没有见过。也许某些变态的需求才用的到吧。


Reply by "dujid", 2006-11-06, 18:03
-----------------------------------------------------

Carl:
但是,众所周知,我们的日常生活中会遇到一些非物质的概念,比如“开灯”这样的动作。既然客观世界中有这样的概念,我们的设计思想就得尽量包容这样的概念。不管你是用对象,还是别的什么东西,我们不能抹杀这种动作的存在。



请不要误解我的意思,我并没有说要抹杀这种动作的存在,我是说这种动作不应该单独存在,应该是附属一个动作的发出者,“开灯”是动作,“开关”就是发出者,两者的关系就是对象与行为。


Carl:

我是唯物主义者,我认为客观世界既然可以全部用物质来描述,我们的程序就一定可以全部用对象来描述。现在我们所使用的面向对象编程中,仍旧有很多面向过程的成分,比如在一个方法的内部。但是我梦想有一天,程序设计完全就是把一堆对象合理的糅合在一起……(别问我,我也不知道到底该怎么揉,仅仅是一个梦)


我上述回帖的目的就是希望大家能换个思想想问题,在我认为,客观世界存在的物质与行为完全可以用程序来抽象,比如一个系统的业务逻辑。因为面向对象为我们定义了 3 种基本的元素: 对象、属性和行为。你甚至可以无限抽象下去,这个力度只是根据你系统的需要而决定。我很赞同你这一点,“程序设计完全就是把一堆对象合理的糅合在一起”,这个目标其实不难实现,关键在于前期的业务抽象。这个才是面向对象应用的王道。至于如何抽象,有时间了我会分享自己的一点体会。


Carl:

回到上面的问题,dujid 的贴子中举了一个delegate的例子。我发表一下我的观点:

我仍旧认为delegate是很好的发明,但是这个例子明显不合理。火药是人类伟大的发明,但你用它来杀人就不对了。用delegate可以写出很糟糕的,不符合人类思维的程序,比如这个例子,但这不能说明delegate本身不合理。


也许是我的例子很糟糕,还望赐教一个更好的应用。


Carl:

那么什么样的例子是合理的?不用我说,大家也能举出一堆:event,ThreadStart,等等。这些delegate确实帮助我们很好的解决了问题。而像这个例子中那样,把delegate当作一个可以直接set的属性的设计,在我的编程生涯中还几乎没有见过。也许某些变态的需求才用的到吧。



我对 C# 里 Event ThreadStart 这些东西统统觉得有问题,一种语言,越简单就越好,越简单才越原始,才是事情的本质。我喜欢 Java,就是因为它简单,它能只让我关注对象的关系,我的所有注意力放在如何抽象事物上,而不是怎么运用技术解决问题。在 ERP、OA 等应用软件领域上,系统的业务是最重要的,也是软件最为复杂的部分,因此,开发人员应该关注的,是如何操作业务对象,而不是解决函数指针问题。语言里有这些技术,很难不让程序员陷入这种技术疑惑当中。

Java 里没有 Event ThreadStart,也没有 delegate,但我却可以实现所有的事情,也可以解决所有的问题,并且没有什么麻烦的,也不会造成什么误解,更不会让人写出直接去 set 什么delegate 属性。而且更重要的是,这一切更加贴切生活,贴切我们的现实。


Reply by "Carl",2006-11-07, 9:47
-----------------------------------------------------

dujid:
我是说这种动作不应该单独存在,应该是附属一个动作的发出者,“开灯”是动作,“开关”就是发出者,两者的关系就是对象与行为。



delegate是对一个对象的行为的封装,而不是只有行为没有对象。只不过在构造delegate的时候,编译器会自己(根据反射)去找这个对象,不需要你显式写出来而已。具体请参考Delegate.CreateDelegate方法。Delegate类型有两个属性,分别是Target和MethodInfo。我们一般只注意到MethodInfo,忽略了Target。


dujid:

我对 C# 里 Event ThreadStart 这些东西统统觉得有问题,一种语言,越简单就越好,越简单才越原始,才是事情的本质。我喜欢 Java,就是因为它简单,它能只让我关注对象的关系,我的所有注意力放在如何抽象事物上,而不是怎么运用技术解决问题。在 ERP、OA 等应用软件领域上,系统的业务是最重要的,也是软件最为复杂的部分,因此,开发人员应该关注的,是如何操作业务对象,而不是解决函数指针问题。语言里有这些技术,很难不让程序员陷入这种技术疑惑当中。



我承认,delegate在C#中是很难理解的,会给初学者带来很大的麻烦。但是很可惜,强大的技术或者思想往往都很难理解。比如,面向对象编程相对面向过程编程要难理解和难掌握。相对论和量子力学远比经典物理学要复杂。

.NET中这些强大到很难理解的东西还有很多,比如反射,inbox/unbox,Dispose,Exception等等,java中也会用到类似的技术。如果我们的目的只是操作业务对象,根本不需要对这些技术有深入的理解,只要会用就行了。如果我们的目的是研究技术,解决技术问题,那你就必须对这些概念有深层次的理解,知道他们是如何实现的。

最后说一下态度的问题,c#的设计师肯定不是白痴,不会莫名其妙设计出这么一个恶心的东西。作为一个程序员,我们应该去学习和了解这种设计背后的原因和思想,而不是在这里发牢骚。.NET的使用者越来越多,这种设计思想是创造还是垃圾,就留给市场去评判吧。


Reply by "dujid", 2006-11-07, 10:08
-----------------------------------------------------

Carl:
.NET中这些强大到很难理解的东西还有很多,比如反射,inbox/unbox,Dispose,Exception等等,java中也会用到类似的技术。如果我们的目的只是操作业务对象,根本不需要对这些技术有深入的理解,只要会用就行了。如果我们的目的是研究技术,解决技术问题,那你就必须对这些概念有深层次的理解,知道他们是如何实现的。

最后说一下态度的问题,c#的设计师肯定不是白痴,不会莫名其妙设计出这么一个恶心的东西。作为一个程序员,我们应该去学习和了解这种设计背后的原因和思想,而不是在这里发牢骚。.NET的使用者越来越多,这种设计思想是创造还是垃圾,就留给市场去评判吧。





我没有比对两种语言的意思,即使在 C# 中,我依然可以不用  Event,  Delegate 而解决问题,直到现在,我始终不能明白为什么我一定要用它,这个是我讨论的目的。严重重审,我没有发牢骚,这个是我对新技术学习的态度,你说它好,那你告诉我为什么要用它,不用它我就写不出好的程序吗?就解决不了问题吗?如果真有一个案例能说明这一点的话,我想我没有任何问题了。

有时间的话,我真心希望你去看一看 java 的 Swing,那是面向对象解决技术问题的典范,Swing 是轻量级 Java 应用程序用户界面的开发 API 包,角色与 MFC 类似,它解决了几乎所有的用户界面的问题,典型的 Panel 布局策略,多种布局方案,Event处理,决不依赖 Windows 的消息机,这些所有的技术问题,都仅仅只用了 3 中类型的对象:类,接口和抽象类,除此以外,没有任何技术,没有 delegate,没有 event 关键字,没有 threadstart。没有用这些,不是一样写出了超强的程序?一样解决了所有的问题?

还有一点很重,就是跨平台依赖性,这个是我欣赏 java 的地方,是我觉得微软别有用心的地方,也是我觉得这些技术被赋予其他含义的地方。


Reply by "WilliamLuo",2006-11-07, 11:07
-----------------------------------------------------

>那你告诉我为什么要用它,不用它我就写不出好的程序吗?就解决不了问题吗?

时至今日,还是有很多同事跟我一样,不太懂得Delegate,可见这不是个非用不可的东西。但是这不能说明Delegate就没有存在的理由。现在的很多好东西,过去都没有,日子也过了,而且也有人写出很好的软件,总不能说现在的新东西都没有存在的必要吧?

另一方面,Carl说的“市场考验”,现在我们很多人并不了解Delegate的典型使用场景和具体使用方法,恰好说明这个东西还没有被市场广泛接受。微软的开发人员当然不傻,但是也许正是他们太聪明了,想要耍点酷、把简单问题搞复杂点,彰显一下自己的卓越,也是可能的吧。个人觉得,不管什么东西,还是应该把门槛搞得低一点,不要叫人望而生畏比较好一点吧。


Reply by "St.Valentine",2006-11-07, 11:12
-----------------------------------------------------

这正说明了MS把Delegate搞得很傻瓜,大家都在用它,但是并不一定每个人都要了解它。

//谁敢说自己在.net没用用过event?

从OOP上来讲,.net中的很多东西是不合格的,比如event,还有更深一点的delegate,但是我想我们不能为了OOP而OOP吧。


Reply by "dujid",2006-11-07, 12:04
-----------------------------------------------------

WilliamLuo:
>那你告诉我为什么要用它,不用它我就写不出好的程序吗?就解决不了问题吗?

时至今日,还是有很多同事跟我一样,不太懂得Delegate,可见这不是个非用不可的东西。但是这不能说明Delegate就没有存在的理由。现在的很多好东西,过去都没有,日子也过了,而且也有人写出很好的软件,总不能说现在的新东西都没有存在的必要吧?



我觉得 delegate 并不是新的技术,更多的像是旁门左道, 本来用好的面向对象的思想是可以解决问题,而且很贴近生活,符合人类原始的思维方式的东西,非要搞出个这么技术化的东西,让程序员还停留在思考技术上。也许太过于偏激,我核心目的是希望大家提高对面向对象的认识,去真正掌握面向对象,而不是别人总结一个,大家才学习一个。


St.Valentine:

从OOP上来讲,.net中的很多东西是不合格的,比如event,还有更深一点的delegate,但是我想我们不能为了OOP而OOP吧。



我想你是没有体会到 OOP 带来的好处,我在这里也不想说 OOP 有什么好处,这些已经被网上的帖子说烂了,无论如何,更好的运用 OOP 确实可以减少很多麻烦, 由于这种思维方式更接近现实,使得我们的代码更加具有阅读性,设计与实现映射的更加紧密,当一个 OO 设计相当好的项目遇到需求变更时,也可以用最短的时间和最少的成本去解决,而不是像我们现在一样,动辄在500行的一个函数中,改动嵌套超过 7、8 层关系的代码,维护组的同事也不用动不动就重写一大堆的代码。倡导 OOP 正是为了解决我们以前在项目中遇到的问题,帮助我们提高效率,降低风险,降低成本。因此,我并不是为了 OOP 而用 OOP。

再回来说 event 和 delegate,它们就于这种贴近现实的努力背道而驰,这是我不赞成使用它的原因,可以想象,如果你的系统中到处充斥着这些技术元素,依然带给我们的是面向过程一样的难题。


Reply by "Razor", 2006-11-07, 12:52
-----------------------------------------------------

这个话题我看就讨论到这里吧,类似的讨论在网络上,在MS和Java两大阵营之间已经有了很多,而且至今似乎谁也没有被说服。



个人建议:

dujid:看来你对OOAD有很深的理解和许多好的想法,希望你能把你的想法更多的share出来,让更多的同事受益,同时相信对你来说也是一个重新提炼的过程,很有好处。另外,能否推荐基本你看过的很好的OOAD方面的书,teacher罗口袋里有钱呀。

carl: 对于delegate,很多人还不太了解它的机理是什么,应该怎么用,什么时候用,什么时候不能用。如果在这些方面你能把你的体会和大家分享的话,我想对于提高公司整体的技术能力是非常有帮助的。



最后,谢谢开此帖的CoreyKou,我想很多人都从这个帖子学到了很多东西。



谢谢!


Reply by "dujid", 2006-11-07, 13:40
-----------------------------------------------------

Razor:
dujid:看来你对OOAD有很深的理解和许多好的想法,希望你能把你的想法更多的share出来,让更多的同事受益,同时相信对你来说也是一个重新提炼的过程,很有好处。另外,能否推荐基本你看过的很好的OOAD方面的书,teacher罗口袋里有钱呀。



我正想如此,推荐大家阅读 《领域驱动设计》,确实是一本好书,对于应用软件设计,特别是 ERP OA 等业务逻辑是主要技术难题的系统。公司有这本书,大家可以在2楼的书架上找到。

读书是一方面,更重要的是尽可能更多的用OO去想问题,这是一个循序渐进的过程,就好比是学习一门语言,学会语法不难,最重要的是学会这门语言的思考方式。



以上全部讨论只为技术,言语多有得罪之处,还请多多包涵。

0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部