<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_金旭亮</title><subtitle type="text">让技术变得有趣，将学习升级为探索</subtitle><id>http://feed.cnblogs.com/blog/u/62255/rss</id><updated>2011-06-19T07:06:03Z</updated><author><name>金旭亮</name><uri>http://www.cnblogs.com/bitfan/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bitfan/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/62255/rss"/><entry><id>http://www.cnblogs.com/bitfan/archive/2011/06/19/2084660.html</id><title type="text">金旭亮《C#面向对象程序设计》2011完整版发布</title><summary type="text">金旭亮《C#面向对象程序设计》教案，针对初学者设计的面向对象入门级参考资料</summary><published>2011-06-19T07:06:00Z</published><updated>2011-06-19T07:06:00Z</updated><author><name>金旭亮</name><uri>http://www.cnblogs.com/bitfan/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bitfan/archive/2011/06/19/2084660.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bitfan/archive/2011/06/19/2084660.html"/><content type="html">&lt;div align="center"&gt;&lt;span style="font-size: x-large;"&gt;《C#面向对象程序设计》教案&lt;/span&gt;&lt;/div&gt;&lt;p align="center"&gt;&lt;span style="font-size: 36pt;"&gt;2011完整版发布&lt;/span&gt; &lt;br /&gt;&lt;/p&gt;&lt;p&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: medium;"&gt;&lt;br /&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: medium;"&gt;&lt;br /&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: medium;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 《C#面向对象程序设计》是我为零面向对象编程基础的学生所设计的教案，共9讲，循序渐进地介绍了在.NET平台开发桌面应用程序所必须掌握的面向对象基础知识，能引导学生迈入面向对象编程技术的大门，并培养出基本的编程技能。&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: medium;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: medium;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 已发布了6讲，今天将剩余的3讲打包一次性地发布。&lt;br /&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: medium;"&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; 各讲内容清单及下载链接如下（注：存放于CSDN下载频道）：&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt; &lt;span style="font-size: medium;"&gt;&lt;br /&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;&lt;a href="http://download.csdn.net/source/3088217"&gt;金旭亮《C#面向对象程序设计》教案_1&lt;/a&gt;  ：CSharp程序设计语言与dotNET面向对象程序设计概述&lt;/span&gt; &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;&lt;a href="http://download.csdn.net/source/3088239"&gt;金旭亮《C#面向对象程序设计》教案_2：CSharp程序设计语言基础&lt;/a&gt; &lt;/span&gt; &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;&lt;a href="http://download.csdn.net/source/3111887"&gt;金旭亮《C#面向对象程序设计》教案_3&lt;/a&gt; ：GUI用户界面设计&lt;/span&gt; &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;&lt;a href="http://download.csdn.net/source/3241223"&gt;金旭亮《C#面向对象程序设计》教案_4&lt;/a&gt; ：类和对象&lt;/span&gt; &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;&lt;a href="http://download.csdn.net/source/3324718"&gt;金旭亮《C#面向对象程序设计》教案_5：继承、接口与多态&lt;/a&gt; &lt;/span&gt; &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;&lt;a href="http://download.csdn.net/source/3324733"&gt;金旭亮《C#面向对象程序设计》教案_6：委托与事件&lt;/a&gt; &lt;/span&gt; &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;&lt;a href="http://download.csdn.net/source/3375239"&gt;&lt;span style="font-size: medium;"&gt;金旭亮《C#面向对象程序设计》教案_完结篇：&lt;br /&gt; &lt;/span&gt; &lt;/a&gt; &lt;/span&gt; &lt;/strong&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;&lt;span style="font-size: medium;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 7 对象集合与对象组合&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8 泛型编程&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; 9 对象间的协作与信息交换&lt;/span&gt; &lt;/span&gt; &lt;/strong&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: medium;"&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 此课程已在北京理工大学成教学院讲授过两轮，教学效果不错。如今发布的是修正过的2011年新版，所用的教材是本人所写的《&lt;a href="http://blog.csdn.net/bitfan/archive/2010/11/06/5991783.aspx"&gt;.NET 4.0面向对象编程漫谈&lt;/a&gt; 》之《基础篇》。&lt;/span&gt; &lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: medium;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 读者如果能切实掌握这9讲所介绍的内容，就迈入了.NET开发的大门，可以进一步地学习与掌握.NET其它技术领域的知识了，而我也计划今后会发布针对数据库，ASP.NET， WCF等技术领域的相关学习资源。&lt;/span&gt; &lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: medium;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 祝大家学习进步。&lt;/span&gt; &lt;/p&gt;  &lt;p&gt;&lt;span style="font-size: medium;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 金旭亮&lt;/span&gt; &lt;/p&gt;&lt;img src="http://www.cnblogs.com/bitfan/aggbug/2084660.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bitfan/archive/2011/06/19/2084660.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bitfan/archive/2011/03/21/1990130.html</id><title type="text">.NET 4.0 技术亮点剖析——在中科院计算所的讲座PPT及源码下载</title><summary type="text">.NET 4.0 技术亮点剖析——我在中科院计算所的讲座PPT下载链接,以及一个“为学生寻找实习机会”的信息。</summary><published>2011-03-21T04:47:00Z</published><updated>2011-03-21T04:47:00Z</updated><author><name>金旭亮</name><uri>http://www.cnblogs.com/bitfan/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bitfan/archive/2011/03/21/1990130.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bitfan/archive/2011/03/21/1990130.html"/><content type="html">&lt;p align="center"&gt;&lt;strong&gt;.NET 4.0 技术亮点剖析&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;#8212;&amp;#8212;在中科院计算所的讲座PPT&lt;/p&gt;&lt;p&gt;2011年3月20日，我在中科院计算所作了一场技术讲座，之后与Jeffery richter和微软的方敏一起回答了与会朋友的提问。&lt;/p&gt;&lt;p&gt;由于时间有限，原先计划讲4部分的内容，只讲完了前3部分，剩余&amp;#8220;动态编程&amp;#8221;一部分未讲。应许多朋友的要求，特将相关资源发布在CSDN下载频道，请访问以下链接下载：&lt;/p&gt;&lt;p&gt;《&lt;a href="http://download.csdn.net/source/3111863" target="_blank"&gt;中科院计算所讲座PPT&amp;#8212;&amp;#8212;.NET 4.0 技术亮点剖析&lt;/a&gt;》&lt;/p&gt;&lt;p&gt;压缩包中是本次讲座的PPT和示例源码，主要内容来自于我写的&lt;a&gt;《.NET 4.0面向对象编程漫谈》&lt;/a&gt;(&lt;a href="http://blog.csdn.net/bitfan/archive/2010/11/06/5991783.aspx"&gt;http://blog.csdn.net/bitfan/archive/2010/11/06/5991783.aspx&lt;/a&gt;)之《应用篇》一书。&lt;/p&gt;&lt;p&gt;另外，继续发布我本学期我给我校成教学院高中起点大专班学生的所设计教案的第3部分&amp;#8212;&amp;#8212;《Windows Forms GUI设计》，这个教案适合于没有或很少面向对象编程经验的学生学习.NET开发。&lt;/p&gt;&lt;p&gt;《&lt;a href="http://download.csdn.net/source/3111887"&gt;Windows Forms GUI设计&lt;/a&gt;》&lt;/p&gt;&lt;p&gt;希望我所发布的这些资源能帮助大家更好更快地掌握.NET软件开发技术。&lt;/p&gt;&lt;p&gt;=====================================&lt;/p&gt;&lt;p&gt;补充：&lt;/p&gt;&lt;p&gt;经常听到业界朋友说招聘到合适的人比较困难，另一方面，鄙人身处校园，学生又常有找工作或实习的需求。&lt;/p&gt;&lt;p&gt;我个人觉得，让学生提前到用人单位去实习是个好方法，对双方都有好处。我这学期既给本科生（大三）讲课，也给研究生（研一）讲课，所以，就产生了以下这个想法：&lt;/p&gt;&lt;p&gt;各位业界朋友们所在公司如果愿意接收在校学生实习的，请把具体的实习岗位、要求掌握的技术或理论知识等相关信息发给我，我会利用上课的机会，将这些信息转发给学生，让他们提前做些准备，然后他们就可以在今年暑期到贵公司实习了。&lt;/p&gt;&lt;p&gt;可以将这些信息发到我的邮箱：&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#116;&amp;#111;&amp;#58;&amp;#74;&amp;#105;&amp;#110;&amp;#88;&amp;#117;&amp;#76;&amp;#105;&amp;#97;&amp;#110;&amp;#103;&amp;#64;&amp;#98;&amp;#105;&amp;#116;&amp;#46;&amp;#101;&amp;#100;&amp;#117;&amp;#46;&amp;#99;&amp;#110;"&gt;JinXuLiang@bit.edu.cn&lt;/a&gt;&lt;/p&gt;&lt;p&gt;或者通过新浪微博即时沟通信息：&lt;/p&gt;&lt;p&gt;&lt;a href="http://t.sina.com.cn/jinxuliang"&gt;http://t.sina.com.cn/jinxuliang&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;    &lt;img src="http://www.cnblogs.com/bitfan/aggbug/1990130.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bitfan/archive/2011/03/21/1990130.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bitfan/archive/2011/03/13/1982744.html</id><title type="text">“智商平平”学软件</title><summary type="text">“智商平平”学软件《软件天才与技术民工》的姊妹篇，再谈智商与软件技术的学习</summary><published>2011-03-13T06:57:00Z</published><updated>2011-03-13T06:57:00Z</updated><author><name>金旭亮</name><uri>http://www.cnblogs.com/bitfan/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bitfan/archive/2011/03/13/1982744.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bitfan/archive/2011/03/13/1982744.html"/><content type="html">&lt;p align="center"&gt;&lt;span style="font-family: 宋体; font-size: 24pt"&gt;&amp;#8220;智商平平&amp;#8221;学软件&lt;/span&gt;&lt;span style="font-size: 24pt"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p align="center"&gt;&lt;span style="font-family: 宋体; font-size: 12pt"&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p align="center"&gt;&lt;span style="font-family: 宋体; font-size: 12pt"&gt;金旭亮&lt;/span&gt;&lt;/p&gt;&lt;p align="center"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;前几天收到了一个在职普通程序员的邮件，在邮件中他说两次报考我们学校计算机专业研究生，但总是惨败而回，第&lt;/span&gt;1&lt;span style="font-family: 宋体"&gt;年总分考了&lt;/span&gt;250&lt;span style="font-family: 宋体"&gt;，砸在政治和数学上，努力复习了一年，又是砸在数学上，总分才&lt;/span&gt;285&lt;span style="font-family: 宋体"&gt;&amp;#8230;&amp;#8230;。我几乎能真切地体会到他那种沮丧和不甘心&amp;#8212;&amp;#8212;为什么我经过一年的辛苦努力，却还是原地踏步并在同一个地方跌倒两次？同样的疑问我也曾经问过自己无数遍，因为我也是连续考研三次才通过的。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;我是一个&amp;#8220;智商平平&amp;#8221;的人，但还算比较努力，有幸&amp;#8220;混入&amp;#8221;高校，成了一名讲授软件开发技术的普通教师。任教&lt;/span&gt;8&lt;span style="font-family: 宋体"&gt;年多以来，接触到了相当数量的学生，有了一些教学经验，同时我还阅读了一些有关教育学心理学方面的书籍和文章，一直在思索这样的一个问题：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-family: 宋体; color: #c00000"&gt;&amp;#8220;智商平平&amp;#8221;的人应该如何自学软件技术，而我又应该如何教&amp;#8220;智商平平&amp;#8221;的人学会软件开发技术？&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;我觉得&amp;#8220;学&amp;#8221;与&amp;#8220;教&amp;#8221;其实是同一个问题的两个不同侧面，都遵循类似的学习与认知规律。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;这里首先要对&amp;#8220;智商平平&amp;#8221;作个界定。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;国外比较重视智商测定，并已发展出了比较成熟的智商测试机制，往往能给某人以一个比较准确的智商测试成绩，这些成绩可被用于高校招生、企业录用员工、军队征兵等。但我们中国这一前提就不存在，比如笔者就从未做过智商测试。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;尽管无法用数字精确地说明，但我们还是可以凭感觉和观察来得出一些结论&amp;#8212;&amp;#8212;&lt;strong&gt;某些人很聪明，某些人则比较笨&amp;#8230;&amp;#8230;&lt;/strong&gt;，比如在同样一所高中里学习的学生，有的能在全国数学、物理等竞赛中屡屡得奖，不用参加高考就能保送到名校，之后顺理成章地继续攻读研究生，甚至能到国外名校去继续深造，考试对于他们来说实在是小菜一碟，想得个低分都不容易&amp;#8230;&amp;#8230;，而许多普通学生，哪怕每天只睡几个小时，日以继夜地做题，高考也得不了几分。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;记得我高考那年有位兄弟就是个典型例子，当我等正在题海中挣扎的时候，这位老兄却捧着本《神雕侠侣》畅游武侠世界，末了人家高考总分还是名列前茅。更有趣的是这位哥们后来学的是经济管理方面专业，毕业后工作没多久突然决定要考研，仅复习半年，就跨专业成为了一名计算机专业研究生&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;还有我的一位师兄，在微软研究院&amp;#8220;混&amp;#8221;，他读博的几年，发论文就象我等编写几个小程序业似的，拿博士学位如探囊取物，这位兄弟给我印象最深的地方在于他曾经想出国准备&lt;/span&gt;GRE&lt;span style="font-family: 宋体"&gt;，一天背&lt;/span&gt;300&lt;span style="font-family: 宋体"&gt;多个单词。我的神啊，我一天能记&lt;/span&gt;100&lt;span style="font-family: 宋体"&gt;个就不错了，而且第&lt;/span&gt;2&lt;span style="font-family: 宋体"&gt;天还没准会忘了&lt;/span&gt;80&lt;span style="font-family: 宋体"&gt;个！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;只要留心一下，会发现我们可以在身边找到许多类似的例子，这些例子说明了一点：&lt;strong&gt;人与人之间是存在着差异的，各有所长，也各有所短&lt;/strong&gt;。我觉得大家公认为聪明的人，其智商应该都属于比较高的，可以合理地假设此人的智商属于人群中最高的&lt;/span&gt;10%&lt;span style="font-family: 宋体"&gt;（即十里选一）那一群体，那么正常情况下，他进入重点大学学习深造应该不成问题，如果是百里选一，那么他进入名校应该问题不大。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;除了智商偏低的人（应该也有&lt;/span&gt;10%&lt;span style="font-family: 宋体"&gt;），中间约占&lt;/span&gt;80%&lt;span style="font-family: 宋体"&gt;的应该是&amp;#8220;不笨也不聪明&amp;#8221;的普通人，而我也属于这个群体，所以我最关注的也就是&amp;#8220;普通人&amp;#8221;的学习问题。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;软件行业从业人员中有两种典型的类型：科研人员与软件工程师。个人感觉，从事科研工作并取得相应成就的人，应该是属于人群中那&lt;/span&gt;10%&lt;span style="font-family: 宋体"&gt;的智商最高的群体，而软件工程师这一工作，则&lt;/span&gt;80%&lt;span style="font-family: 宋体"&gt;的普通人经过训练都可以胜任，但要达到一流的水平，对其智商的要求也是相当高的。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;科研领域取得成就的人，还有那些优秀的软件工程师，突出的一点是他们的抽象思维能力较高，而体现抽象思维能力水平最直接的标志，就是数学。我发现计算机科学研究弄到后头，来来回回摆弄的都是数学；另一方面，对于高水平的软件系统开发，与数学有很密切联系的计算机算法、数据结构、编译原理等比较抽象复杂的计算机科学理论的作用也开始突显。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;前段时间，机械工业出版社送给我了一本《深入计算机系统（第&lt;/span&gt;2&lt;span style="font-family: 宋体"&gt;版）》，这本书以程序员的视角从底向上地介绍计算机系统的各个方面，许多人说这是本好书。有趣的是，在新浪微博上我看到有网友说：&amp;#8220;&lt;strong&gt;这本书太枯燥了，根本看不下去&amp;#8221;&lt;/strong&gt;。我为此也发了一条微博和他一起交流：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体; color: #c00000"&gt;觉得技术书枯燥与没兴趣，可能关键在于你实际开发经验不多，所以缺乏理解这些书所需的一些基础。个人体会，当某本书大多数人说好，而自己觉得很枯燥的，日后很有可能会发现原因在于自己第一次阅读时还没有具备看懂它的基础，无法引发共鸣&lt;/span&gt;&lt;span style="color: #c00000"&gt;&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;这的确是我亲身体会。&lt;strong&gt;许多复杂抽象的计算机科学理论，在自己还没有具备相应的基础前，别去碰它，否则，收获的将只有挫折与失望。&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;举个例子：还没有使用编程语言亲自编程的体验，《编译原理》是学不会的；有的人高中数学其实都没掌握好，却想通过阅读《算法导论》来成长为一名算法高手，似乎也没这可能；同样的，如果没有足够的开发设计经验，却抱本《设计原本》（&lt;/span&gt;&lt;span style="letter-spacing: 0.4pt"&gt;The Design of Design: Essays from A Computer Scientist&lt;/span&gt;&lt;span style="font-family: 宋体"&gt;）来啃，我只能对着你长长地叹息一声&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;大家都急，想迅速成功，想迅速达到自己的目标，都等不了了，我也一样，但世界自有其规律，主观归主观，客观归客观，客观世界不会&amp;#8220;听从&amp;#8221;人的主观愿望，&amp;#8220;人有多大胆，地有多大产&amp;#8221;注定是一个神话&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;很明显，&lt;strong&gt;每个人都应该想办法弄清楚自己的&amp;#8220;家底&amp;#8221;，然后选择最适合自己的学习方式&lt;/strong&gt;。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;时间倒推&lt;/span&gt;30&lt;span style="font-family: 宋体"&gt;年，那时只有很少数的人可以上大学，这些人绝大多数属于人群中较聪明的那一族，所以，整个大学教育体制其实偏向于&amp;#8220;精英教育&amp;#8221;，其主要目的是培养精英和栋梁之才。而&lt;/span&gt;21&lt;span style="font-family: 宋体"&gt;世纪以后，大批的普通智商的学生进入校园，从总体上来说，除了少数名校，大学教育应该转向&amp;#8220;平民教育&amp;#8221;。&lt;/span&gt; &lt;span style="font-family: 宋体"&gt;而中国教育最大的问题也在这：由于众所周知的原因，很多大学属于&amp;#8220;反应迟缓&amp;#8221;并&amp;#8220;拒绝改变&amp;#8221;的&amp;#8220;恐龙&amp;#8221;，仍然采用&amp;#8220;精英&amp;#8221;教育的传统方式方法教学，这本质上就是将原来只针对少数优秀学生的教育方式与方法给&amp;#8220;人为放大&amp;#8221;，具体现象之一就是原先的十几人的小班变成了几十人甚至是上百人的大班。要知道，近十多年以来中国高等教育的重大变化不仅仅体现在学生规模的激增上，还体现在学生平均智商与素质的&amp;#8220;普通化&amp;#8221;。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;用&amp;#8220;放大&amp;#8221;的精英模式教育大批的&amp;#8220;普通人&amp;#8221;，正如没有刘翔的身体素质，却按照刘翔的训练方法训练，用脚思索都会发现这是不太对头的。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;拿计算机专业来说，近些年来虽然在不断的调整，但目前仍然是&amp;#8220;理论&amp;#8221;重于&amp;#8220;实践&amp;#8221;。前面也说过，复杂抽象的计算机理论课，绝不是那么好学与好理解好掌握的，有些课程，真的应该只针对那些比较聪明的学生来讲，而即使是所有学生都要学的同一门必修课程，针对不同层次的学生，也应该有不同的讲法。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;好了，就软件这个领域，&amp;#8220;智商平平&amp;#8221;的普通人应该如何有效地学习？&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-family: 黑体; color: #c00000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="font-family: 黑体; color: #c00000"&gt;我觉得，&amp;#8220;智商平平&amp;#8221;的普通人学软件，在一开始应该避开那些复杂抽象的要求有较高学习能力的计算机科学理论课程，特别是那些要求有实践作基础的课，应从能&amp;#8220;即时反馈&amp;#8221;并能&amp;#8220;立即用于开发实践&amp;#8221;的专业课程与开发技术入手。&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;举个例子，是否学生要学的第一门编程语言必须要是&lt;/span&gt;C&lt;span style="font-family: 宋体"&gt;语言？这个问题就可以讨论。我个人觉得，尽管从&lt;/span&gt;C&lt;span style="font-family: 宋体"&gt;入手是经典途径，已经多年的实践检验，但这并不排斥可以采用其他的方式。比如，能否一开始就直接学&lt;/span&gt;Python&lt;span style="font-family: 宋体"&gt;？诸如&lt;/span&gt;Python&lt;span style="font-family: 宋体"&gt;这类的动态编程语言，具有语法简单、反馈迅速的特点，很有助于学生理解编程语言，培养软件开发的思维方式。我还尝试过一开始就直接让学生学习面向对象的编程语言（比如&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;），哪怕他们没学过&lt;/span&gt;C&lt;span style="font-family: 宋体"&gt;，但使用&lt;/span&gt;Visual Studio&lt;span style="font-family: 宋体"&gt;这种高度智能化的开发环境，以可视化的方式设计软件，最终能开发出真正可以在日常使用的软件，对学生还是有着很强的吸引力，不象&lt;/span&gt;C&lt;span style="font-family: 宋体"&gt;，学了一个学期，学生还只是编写几个&amp;#8220;黑底白字&amp;#8221;的小程序，根本就不知道现在的可视化软件是怎么写出来的，太有挫败感了。特别是&lt;/span&gt;C++&lt;span style="font-family: 宋体"&gt;，我觉得通过它来给刚学完&lt;/span&gt;C&lt;span style="font-family: 宋体"&gt;的学生讲面向对象编程，实在是个杯具，有几个学生真能在短短的一学期课程中搞得掂&lt;/span&gt;C++&lt;span style="font-family: 宋体"&gt;这么复杂的编程语言，而且还要求他们理解面向对象的思想并能用它写出真正可用的软件？我觉得，学完&lt;/span&gt;C&lt;span style="font-family: 宋体"&gt;之后，用&lt;/span&gt;Java&lt;span style="font-family: 宋体"&gt;或&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;课程来帮助学生掌握面向对象的编程语言与思想，要比&lt;/span&gt;C++&lt;span style="font-family: 宋体"&gt;好得多。而且学生通过&lt;/span&gt;Java&lt;span style="font-family: 宋体"&gt;或&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;掌握面向对象的基本思想与理论之后，再去学&lt;/span&gt;C++&lt;span style="font-family: 宋体"&gt;就好多了。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&lt;span style="font-family: 黑体; color: #c00000"&gt;计算机科学与技术有很多个子领域，学习顺序其实是很重要的。&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;我个人认为，计算机专业的学生应该在大一，最晚不要拖到大二，就掌握一门主流的编程语言和开发工具，&lt;/span&gt;Java&lt;span style="font-family: 宋体"&gt;和&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;是两个好的选择，为什么要这么做？道理很简单，你掌握了它们，就可以迅速地投身于软件开发实践，并且有助于掌握后继的计算机专业课程理论。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;举个例子，在大一大二就使用&lt;/span&gt;Java&lt;span style="font-family: 宋体"&gt;或&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;写过多线程程序的学生，在学习《操作系统》这门课程时将要轻松得多，而能在大学低年级就开始编写游戏的学生，往往会对《数据结构》、《人工智能》、《图形图像处理》等理论课程感兴趣，他就会主动地去学习相关的游戏开发平台与工具，学习&lt;/span&gt;C++&lt;span style="font-family: 宋体"&gt;这种复杂的编程语言就会有强大的动力，因为许多游戏引擎是采用&lt;/span&gt;C++&lt;span style="font-family: 宋体"&gt;编写的&amp;#8230;&amp;#8230;。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;在&amp;#8220;无网不胜&amp;#8221;的网络时代，学生掌握了&lt;/span&gt;Java&lt;span style="font-family: 宋体"&gt;、&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;或&lt;/span&gt;C++&lt;span style="font-family: 宋体"&gt;之类主流的编程语言之后，他就具备了进军网络开发领域的可能，此时，他再学习《计算机网络》这门课程就水到渠成了，他可以将已具备的软件开发能力与相关计算机网络理论结合起来，自己开发一个&lt;/span&gt;Web&lt;span style="font-family: 宋体"&gt;服务器，自己开发一个&lt;/span&gt;QQ&lt;span style="font-family: 宋体"&gt;，自己开发一个网络游戏，自己写个互联网工具，自己写个跑在手机上的应用&amp;#8230;&amp;#8230;，其所获得的成就感是枯燥的&amp;#8220;空对空&amp;#8221;理论学习所无法比拟的。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;写到这，不妨作个阶段的小结：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family: 黑体; color: #c00000"&gt;软件技术怎么学？如果你属于&amp;#8220;智商平平&amp;#8221;的普通人，那么，请从动手编写小程序入手，在开发实践的基础上去学习计算机科学理论。&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;在具体技术领域的学习上，需要谨慎选择学习的方式与材料，当此领域内的某本经典著作你怎么也看不懂或觉得很枯燥时，请另选一本比较浅显的，或者咨询一下这个领域内的人，了解一下掌握这个领域的技术需要哪些前提，把这些欠缺的东西补上之后，这些书你就看得懂了，甚至是看得津津有味。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;这里谈谈我的体会。我以前从未觉得有必要去了解各种网络协议的细节，但后来有了一些网络应用程序的开发经验，并且尝试分析&lt;/span&gt;.NET&lt;span style="font-family: 宋体"&gt;基类库中相关网络组件的设计时，就体会到如果不了解网络协议的特点，就难于了解为什么设计者会以这种方式来封装网络功能。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;蔡学镛先生曾发过一篇微博，推荐大家看看《&lt;/span&gt;HTTP: The Definitive Guide&lt;span style="font-family: 宋体"&gt;》一书，后来我在网上找到了这本详细介绍&lt;/span&gt;HTTP&lt;span style="font-family: 宋体"&gt;协议各个方面技术细节的书，翻阅之后，对原先的许多有关&lt;/span&gt;Web&lt;span style="font-family: 宋体"&gt;开发的问题有了新的看法，很有收获。然而，如果某人没有开发&lt;/span&gt;Web&lt;span style="font-family: 宋体"&gt;应用程序的经验，恐怕又会说这本书&amp;#8220;枯燥&amp;#8221;了。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;如果阅读本文的还是在校学生，他们可能说：&amp;#8220;&lt;strong&gt;老师，我们没有选择课程与学习方式的余地，学校安排了这么多的必修课程，不硬着头皮去啃，我怎么毕业啊？&lt;/strong&gt;&amp;#8221;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;而另一些已经工作的朋友则会说：&amp;#8220;&lt;strong&gt;每天都有那么多的工作，很难有这个时间和精力按照你所说的方法去学习&lt;/strong&gt;。&amp;#8221;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;这确实是个问题，但我也没解决办法，因为我们所处的环境我们没有选择权。在这里，我只是向大家描绘一下：&lt;strong&gt;我认为合理的软件技术学习方式应该是怎样的&lt;/strong&gt;。而且我也看到了，正是因为违背了这些教育与学习的基本原则，中国大学才被国民&amp;#8220;千夫所指&amp;#8221;。这么多年来，中国大学在&amp;#8220;培养真正的精英与栋梁之才&amp;#8221;方面国民是不满意的（不然为什么会有钱学森的&amp;#8220;世纪之问&amp;#8221;并引发广泛共鸣？）。事实证明，中国大学这么些年来，精英没培养出来，大批的普通学生也没教育好，他们中的许多直到毕业也没有能掌握一些必要的职业技能，高不成低不就的，找工作困难，另一方面，&lt;/span&gt;IT&lt;span style="font-family: 宋体"&gt;企业许多岗位缺人却同样找不到能胜任工作要求的人才，整个一&amp;#8220;死循环&amp;#8221;&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;莫谈国事，还是聊聊&amp;#8220;笨&amp;#8221;与&amp;#8220;聪明&amp;#8221;的问题。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;前面我说过了，整个人群总可以划分为&lt;/span&gt;10%&lt;span style="font-family: 宋体"&gt;比较聪明的，&lt;/span&gt;10%&lt;span style="font-family: 宋体"&gt;比较&amp;#8220;笨&amp;#8221;的，余下&lt;/span&gt;80%&lt;span style="font-family: 宋体"&gt;的&amp;#8220;普通人&amp;#8221;。其实所谓&amp;#8220;比较聪明&amp;#8221;的人，主要体现在他反应快，记忆力强，抽象思维水平高，学习能力强，掌握新知识、新技能的速度快，投入少而收益大，&amp;#8230;&amp;#8230;，但这并不意味着许多知识与技能只有聪明人才能掌握。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;对于占&lt;/span&gt;80%&lt;span style="font-family: 宋体"&gt;的普通人而言，绝大多数聪明人所掌握的知识与技能也是完全可以掌握的，只不过需要更长的时间、更多的精力和更强的毅力，套句老话，就是要&amp;#8220;&lt;strong&gt;笨鸟先飞&lt;/strong&gt;&amp;#8221;。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;如果把智商高的那批人比作兔子，普通人比作乌龟，那么从理论上讲，兔子能到的地方，只要给与足够的时间，乌龟也是能爬到那的。当然，由于人的生命有限，对于那些从不偷懒的兔子，乌龟要达到这些兔子所到达的地方，是不可能的。然而老天比较公平，人性也有弱点，本身跑得快又不偷懒的兔子，在兔子这一群体中比例并不高，许多兔子往往会由于看到那么多的乌龟落在自己的后面，他们做事的方法那么低效那么笨，素质也差，就充满了优越感，往往会变得浮燥，不愿再辛勤努力了，结果他们最终也没有取得大的成就。相反，乌龟就没有任何骄傲的资本，乌龟中的那些上进的人，往往具有很强的坚持精神，不停地爬呀爬的，而且在爬的过程中他们会不断地动脑筋想点子，怎样爬得更快？结果大家都知道，有些乌龟，爬到了许多兔子所没能到达的地方。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;金庸先生的名著《射雕英雄传》其实是一个经典的&amp;#8220;龟兔赛跑&amp;#8221;故事，比较&amp;#8220;笨&amp;#8221;的郭靖，其最终的成就比&amp;#8220;聪明&amp;#8221;的杨康要大得多，而小说中所描写的郭靖的学艺过程与心理活动和体验，实在是太切合实际了。我推荐所有的&amp;#8220;乌龟&amp;#8221;们好好地读读《射雕英雄传》，重点看看郭靖的成长过程。我有时在想，金庸先生是怎样的一个人，能将一个&amp;#8220;笨人&amp;#8221;的故事讲到这般的精彩？我觉得说金庸先生属于&amp;#8220;跑得快的兔子&amp;#8221;行列大家应该不会有异议，但我必须同时指出，他绝对是一只不偷懒的兔子，想想看，有几只偷懒的&amp;#8220;兔子&amp;#8221;能写出&lt;/span&gt;14&lt;span style="font-family: 宋体"&gt;部雅俗共赏的小说？更关键的是，这些小说部部不同，每部都有自己的风格，创新、创新，还是创新，绝不重复昨天的成功，结果让金庸先生在武侠小说领域成为他人难以企及的高峰&amp;#8230;&amp;#8230;。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;所以，即使是天才，不努力，也是废材，即使&amp;#8220;智商平平&amp;#8221;，坚持下去，也能爬得很远，但对于那些勤奋努力的天才，我想，大家一定会怀着敬意地提到他们的名字&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-family: 宋体"&gt;这就是&amp;#8220;聪明&amp;#8221;与&amp;#8220;笨&amp;#8221;的辩证法。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;=========================================================================&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;span style="font-family: 宋体; font-size: 24pt"&gt;&lt;strong&gt;附录：&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;这个学期我给本校成教学院&amp;#8220;高中起点大专班&amp;#8221;的学生讲授《&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;面向对象程序设计》课程，为此，我设计了一套针对零面向对象编程基础的学生（但要求他们学过&lt;/span&gt;C&lt;span style="font-family: 宋体"&gt;语言）学习面向对象技术的教案，今天发布前两讲《&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;程序设计语言与&lt;/span&gt;.NET&lt;span style="font-family: 宋体"&gt;面向对象程序设计概述》和《&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;程序设计语言基础》。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;欲作其事，先正其意。因此《概述》一讲中我分析了当前计算机教育的现状，介绍了软件技术的学习方法；而在《&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;程序设计语言基础》一讲中，我针对学生几乎没有写过程序的现状，我采用了现场编程演示和现场上机练习的教学方式，要求学生自带笔记本电脑，跟着教师同步地在课堂上键入代码，然后马上现场完成一些小的编程任务的方式，有问题及时反馈，现场解决，同时留了课后作业。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;我希望这些课程能帮助学生迈入软件开发的大门。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;后续的课程教案将陆续发布，可供讲授《&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;面向对象程序设计》课程的教师参考，也可以作为&lt;/span&gt;C#&lt;span style="font-family: 宋体"&gt;的初学者的自学资料。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: 宋体"&gt;请点击以下链接下载教案及相关源码（在博客园）。&lt;/span&gt;&lt;/p&gt;&lt;p align="left"&gt;&lt;span style="font-size: 14pt"&gt;1 &lt;/span&gt;&lt;span style="font-family: 宋体; font-size: 14pt"&gt;《&lt;/span&gt;&lt;a href="http://files.cnblogs.com/bitfan/CSharp%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E8%AF%AD%E8%A8%80%E4%B8%8EdotNET%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E6%A6%82%E8%BF%B0.rar"&gt;&lt;span style="font-size: 14pt"&gt;C#&lt;/span&gt;&lt;span style="font-family: 宋体; font-size: 14pt"&gt;程序设计语言与&lt;/span&gt;&lt;span style="font-size: 14pt"&gt;.NET&lt;/span&gt;&lt;span style="font-family: 宋体; font-size: 14pt"&gt;面向对象程序设计概述&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: 宋体; font-size: 14pt"&gt;》&lt;/span&gt;&lt;/p&gt;&lt;p align="left"&gt;&lt;span style="font-size: 14pt"&gt;2 &lt;/span&gt;&lt;span style="font-family: 宋体; font-size: 14pt"&gt;《&lt;/span&gt;&lt;a href="http://files.cnblogs.com/bitfan/CSharp%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E8%AF%AD%E8%A8%80%E5%9F%BA%E7%A1%80.rar"&gt;&lt;span style="font-size: 14pt"&gt;C#&lt;/span&gt;&lt;span style="font-family: 宋体; font-size: 14pt"&gt;程序设计语言基础&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: 宋体; font-size: 14pt"&gt;》&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/bitfan/aggbug/1982744.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bitfan/archive/2011/03/13/1982744.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bitfan/archive/2011/01/18/1938365.html</id><title type="text">《.NET 4.0网络开发入门之旅》7：填平缓冲区陷阱</title><summary type="text">《.NET 4.0网络开发入门之旅》7：填平缓冲区陷阱</summary><published>2011-01-18T06:58:00Z</published><updated>2011-01-18T06:58:00Z</updated><author><name>金旭亮</name><uri>http://www.cnblogs.com/bitfan/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bitfan/archive/2011/01/18/1938365.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bitfan/archive/2011/01/18/1938365.html"/><content type="html">&lt;div&gt;&lt;p&gt;&lt;span style="font-size: small;"&gt;《.NET 4.0网络开发入门之旅》&amp;#8212;&amp;#8212;&lt;br /&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;span style="font-size: small;"&gt;&lt;strong&gt;&lt;span style="font-size: x-large;"&gt;填平缓冲区陷阱&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;strong&gt; &lt;/strong&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; &lt;/span&gt; &lt;/p&gt; &lt;div&gt; &lt;p align="left"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 宋体;"&gt;注：&lt;/span&gt; &lt;/span&gt;   &lt;/p&gt; &lt;p align="left"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt; &lt;span style="font-family: 宋体;"&gt;这是一个针对&lt;/span&gt; &lt;span style="font-family: 宋体;"&gt;&lt;strong&gt;网络开发领域初学者&lt;/strong&gt; 的系列文章，可作为《&lt;a href="http://blog.csdn.net/bitfan/archive/2010/11/06/5991783.aspx"&gt;&lt;span style="color: blue;"&gt;.NET 4.0  &lt;span style="color: blue;"&gt;面向对象编程漫谈  &lt;/span&gt;   &lt;/span&gt; &lt;/a&gt;   &lt;/span&gt;   》一书的扩充阅读，写作过程中我假设读者可以对照阅读此书的相关章节，不再浪费笔墨重复介绍相关的内容。  &lt;/span&gt;    &lt;/p&gt; &lt;p align="left"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt; &lt;span style="font-family: 宋体;"&gt;对于其他类型的读者，除非您已经有相应的.NET  技术背景与一定的开发经验，否则，阅读中可能会遇到困难。&lt;/span&gt; &lt;/span&gt;      &lt;/p&gt; &lt;p align="left"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt; &lt;span style="font-family: 宋体;"&gt;我希望这系列文章能让读者领略到网络开发的魅力！&lt;/span&gt; &lt;/span&gt;      &lt;/p&gt; &lt;p align="left"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt; &lt;span style="font-family: 宋体;"&gt;另外，这些文章均为本人原创，请读者尊重作者的劳动，我允许大家出于知识共享的目的自由转载这些文章及相关示例，但未经本人许可，请不要用于商业盈利目的。&lt;/span&gt; &lt;/span&gt;    &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 本文如有错误，敬请回贴指正。 &lt;/span&gt; &lt;/p&gt; &lt;p align="left"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt; &lt;span style="font-family: 宋体;"&gt;谢谢大家！&lt;/span&gt; &lt;/span&gt;      &lt;/p&gt; &lt;p align="left"&gt;&amp;nbsp; &lt;/p&gt; &lt;p align="left"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 宋体;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt; &lt;span style="font-family: 宋体;"&gt;金旭亮&lt;/span&gt; &lt;/span&gt;    &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;=================================================&lt;/span&gt; &lt;/p&gt; &lt;p align="left"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 宋体;"&gt;点击以下链接阅读本系列前面的文章：&lt;/span&gt; &lt;/span&gt;   &lt;/p&gt; &lt;p align="left"&gt;&amp;nbsp; &lt;/p&gt; &lt;span style="font-size: small;"&gt;&lt;span style="font-family: 宋体;"&gt;&lt;a href="http://blog.csdn.net/bitfan/archive/2010/12/01/6047911.aspx"&gt;&lt;span style="color: blue;"&gt;1 《&lt;/span&gt;     &lt;span style="color: blue;"&gt;开篇语&amp;#8212;&amp;#8212;   &lt;/span&gt;   &lt;span style="color: blue;"&gt;无网不胜》&lt;/span&gt; &lt;/a&gt; &lt;/span&gt; &lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;a href="http://blog.csdn.net/bitfan/archive/2010/12/06/6058227.aspx" target="_blank"&gt;2 《  IP知多少》 &lt;/a&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;3 《&lt;a href="http://blog.csdn.net/bitfan/archive/2010/12/10/6067800.aspx"&gt;我在&amp;#8220;网&amp;#8221; 中央 &lt;/a&gt; 》&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;4 《&lt;a href="http://blog.csdn.net/bitfan/archive/2010/12/24/6097011.aspx" target="_blank"&gt;与Socket的第一次&amp;#8220;约会&amp;#8221;&lt;/a&gt; 》&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span style="font-size: small;"&gt;5 《&lt;a href="http://blog.csdn.net/bitfan/archive/2011/01/05/6118185.aspx"&gt;与Socket的&amp;#8220;再次见面&amp;#8221;&lt;/a&gt; 》&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;6 《&lt;a href="http://blog.csdn.net/bitfan/archive/2011/01/10/6126536.aspx"&gt;&amp;#8220;麻烦&amp;#8220;的数据缓冲区&lt;/a&gt; 》&lt;br /&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;=========================================&lt;/p&gt; &lt;p&gt;&lt;br /&gt; &lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 前一篇文章《&amp;#8220;&lt;a href="http://blog.csdn.net/bitfan/archive/2011/01/10/6126536.aspx" target="_blank"&gt;引发麻烦&amp;#8221;的缓冲区&lt;/a&gt; 》，介绍了TCP Socket编程数据缓冲区必须要注意的两个问题：&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; （1）TCP不保存消息的边界，因此，服务端必须能有一种方法从收到的数据中正确地&amp;#8220;切分&amp;#8221;出一条完整的消息&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; （2）客户端与服务端的数据发送和接收速率应该匹配，否则，有可能出现&amp;#8220;黏包&amp;#8221;和&amp;#8220;丢包&amp;#8221;现象。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 那么，我们怎么样来解决这两个问题？&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;span style="font-size: large;"&gt;1 为要传输的多条消息规定统一的长度&lt;/span&gt; &lt;/strong&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;  这是最直观的方法，我们可以事先制定一个消息代码表，每个消息代码都代表不同的含义，比如&amp;#8220;000&amp;#8221;代表&amp;#8220;初始化&amp;#8221;，&amp;#8220;999&amp;#8221;表示&amp;#8220;结束&amp;#8221;之类，这种思 想在HTTP中我们也可以看到，比如HTTP就定义了一些状态码，200代表&amp;#8220;OK&amp;#8221;，500代表&amp;#8220;服务端内部错误&amp;#8221;。还可以参考CPU指令的设计方法， 自行制定一些定长的&amp;#8220;消息代码表&amp;#8221;。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 由于所有消息长度都一致，服务端的处理将变得非常简单，它将收到的数据按约定的长度&amp;#8220;切块&amp;#8221;即可。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 请看示例解决方案FixedSizeMessageDemo。客户端需要将一个int数组发给服务端，服务端使用一个MemoryStream保存这些数据，然后按照4个字节一块一块地读取它们，正确地还原数据。 &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 以下是服务端的代码框架：&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; int recv = 0;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; //用于暂存数据的内存流&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; MemoryStream mem = new MemoryStream();&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; while (true)&amp;nbsp; //接收客户端发来的所有数据&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //将接收到的数据保存到内存流中&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; recv = client.Receive(data);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; mem.Write(data, 0, recv);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (recv == 0) //数据接收完毕，断开客户端 {0} 连接&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; client.Close();&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; mem.Seek(0, SeekOrigin.Begin);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; long datalength = mem.Length;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BinaryReader reader = new BinaryReader(mem);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("接收到数据为：");&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (reader.BaseStream.Position &amp;lt; datalength)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //切分数据&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Write("{0},", reader.&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;ReadInt32()&lt;/strong&gt; &lt;/span&gt; );&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; reader.Close();&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-size: large;"&gt;&lt;strong&gt;&amp;nbsp; 2 给消息附加长度信息&lt;/strong&gt; &lt;/span&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 使用定长的消息虽然可以简化服务端的代码，但却受到很大的限制，而且如何设计一整套消息代码也是件比较麻烦的事。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 一种比较好的方式是将两者结合起来，在每个消息开头附加一个固定长度的&amp;#8220;消息长度&amp;#8221;信息，这样，服务端就知道本消息到底有多长。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; HTTP协议就是这么干的，在HTTP响应消息的头部（Headers）中有一个Content-length项，通知浏览器HTTP消息的主体（Body）部分占多少个字节。&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #993300;"&gt;提示：&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; HTTP是应用层协议，它在底层依赖TCP协议完成HTTP消息的传输。&lt;/span&gt; &lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 首先，我们设计一个发送数据的静态方法：&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; // 发送变长的数据，将数据长度附加于数据开头&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; public static int SendVarData(Socket s, byte[] data)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int total = 0;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int size = data.Length;&amp;nbsp; //要发送的消息长度&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int dataleft = size;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //剩余的消息&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int sent;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //将消息长度（int类型）的，转为字节数组&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] datasize = new byte[4];&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; datasize = BitConverter.GetBytes(size);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //将消息长度发送出去&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sent = s.Send(datasize);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //发送消息剩余的部分&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (total &amp;lt; size)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sent = s.Send(data, total, dataleft, SocketFlags.None);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; total += sent;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dataleft -= sent;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return total;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 仔细看一下注释，上述代码完成的工作&amp;#8220;一目了然&amp;#8221;，无需废话。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 以下静态方法则完成接收并切分消息的工作：&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 接收变长的数据，要求其打头的4个字节代表有效数据的长度&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static byte[] ReceiveVarData(Socket s)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (s == null)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new ArgumentNullException("s");&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int total = 0;&amp;nbsp; //已接收的字节数&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int recv;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //接收4个字节，得到&amp;#8220;消息长度&amp;#8221;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] datasize = new byte[4];&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; recv = s.Receive(datasize, 0, 4, 0);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int size = BitConverter.ToInt32(datasize, 0);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //按消息长度接收数据&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int dataleft = size;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] data = new byte[size];&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (total &amp;lt; size)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; recv = s.Receive(data, total, dataleft, 0);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (recv == 0)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; total += recv;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dataleft -= recv;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return data;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 可以看到，由于&amp;#8220;事先&amp;#8221;知道消息长度，接收消息变得非常直观。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 为了方便重用，我们可以把上述两个静态方法放到一个静态类SocketHelper中，并且将此类添加到MyNetworkLibrary类库中。以后的例子，还会用到这两个方法。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 示例解决方案VariableLengthMessageDemo展示了使用上述方法发送变长数据。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;span style="font-size: large;"&gt;3 &amp;#8220;一问一答&amp;#8221;的数据传送&lt;/span&gt; &lt;/strong&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 仔细分析一下TCP协议，会发现它其实是通过&amp;#8220;一问一答&amp;#8221;的&amp;#8220;握手&amp;#8221;方式实现数据的可靠传输。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 我们可以依葫芦画瓢，在更高的层次实现&amp;#8220;一问一答&amp;#8221;的通讯，简单地说：&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #993300;"&gt;数据发送方发送完一条消息之后，就停下来等待接收方发来一个确认消息，收到之后，再发送第二条消息。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 数据接收方由于确切地知道发送方一次只发送一条消息，所以，它可以&amp;#8220;放心大胆&amp;#8221;地不断接收数据，直到receive方法返回0为止，然后，再向发送方发送一条&amp;#8220;消息已收到&amp;#8221;的&amp;#8220;通知&amp;#8221;，然后，准备接收下一条消息。&lt;/span&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 对于这种方式的数据通讯，每条消息可以不必附加上长度信息。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 请看示例解决方案SendAndWaitDemo。客户端发送数据完毕之后，发送一条&amp;#8220;SendFinished&amp;#8221;消息。  服务端接收完数据之后，发送一条&amp;#8220;ReceiveFinished&amp;#8221;消息。 客户端没收到&amp;#8220;ReceiveFinished&amp;#8221;消息，就不会发送新的消息。  &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 就请读者自行阅读源码，不再赘述。&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;strong&gt;&lt;span style="font-size: large;"&gt;&amp;nbsp; 4 开发一个&amp;#8220;网络计算器&amp;#8221;&lt;/span&gt; &lt;/strong&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 前面介绍的许多示例程序都是出于学习目的而设计的，几乎没有什么实际用途，在学习了这么多的Socket编程知识之后，我们终于具备了开发一个&amp;#8220;有点用&amp;#8221;的网络应用程序的前提。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 我在《.NET  4.0面向对象编程漫谈》一书的第24章，介绍了一个支持加减乘除和多级括号的&amp;#8220;四则运算计算器&amp;#8221;，并且将相关的前序、中序表达式解析算法封装成了一个程 序集MathFuncLib.dll。我们就通过重用这个程序集，加上新学的Socket编程技术，实现一个&amp;#8220;网络版四则运算计算器&amp;#8221;（示例程序 NetworkCalculator）。&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;div align="center"&gt;&lt;img src="http://hi.csdn.net/attachment/201101/18/0_1295333068N6Bm.gif" alt="" /&gt;&lt;/div&gt; &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;span style="font-size: small;"&gt; &amp;nbsp;图 1&lt;/span&gt;&lt;/div&gt;&lt;p&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  上述示例程序客户端使用前面介绍的SendVarData方法发送表达式，使用ReceiveVarData方法接收服务端发回的计算结果。服务端使用 MathFuncLib程序集封装的中序算法解析表达式，它的表达式接收和发回计算结果也是用的ReceiveVarData和SendVarData方 法。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 请读者自行阅读源码。&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 最后留几个作业：&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 请读者应用《&lt;a href="http://blog.csdn.net/bitfan/archive/2010/11/06/5991783.aspx"&gt;.NET 4.0面向对象编程漫谈&lt;/a&gt; 》中介绍的多线程技术，改造NetworkCalculator示例程序：&lt;br /&gt; &amp;nbsp;&amp;nbsp; （1）让服务端可以同时响应多个客户端的表达式计算请求&lt;br /&gt; &amp;nbsp;&amp;nbsp; （2）将客户端由Console程序改为Windows Forms或WPF程序，在后台启动线程发送和接收表达式及计算结果。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;再来点难度大的：&lt;br /&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 为了提升处理效率，允许客户端将&amp;#8220;多条要计算的表达式&amp;#8221;打包在一起，一起发送给服务端，服务端计算完毕之后，再把所有结果也&amp;#8220;打包&amp;#8221;一次性地发回给客户端。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 应用本文所介绍的技术，现在读者您能开发出这样的程序吗？&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 下一讲，我们将暂时&amp;#8220;告别一下&amp;#8221; TCP，而去领略一下另一个非常重要的协议--UDP的风彩！&lt;br /&gt; &lt;br /&gt; ===============================================================================&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 有关&amp;#8220;四则运算计算器&amp;#8221;示例程序和MathFuncLib.dll的详细介绍，请看《&lt;a href="http://blog.csdn.net/bitfan/archive/2010/11/06/5991783.aspx"&gt;.NET 4.0面向对象编程漫谈&lt;/a&gt; 》一书的第24章，读者可以从书的配套资源包中找到下载链接。以下列出博客园中的下载链接：&lt;/span&gt; &lt;/p&gt; &lt;h3 align="center"&gt;&lt;div&gt;&lt;a href="http://files.cnblogs.com/bitfan/%e4%bb%8e%e9%9d%a2%e5%90%91%e5%af%b9%e8%b1%a1%e5%88%b0SOA.rar"&gt;《从面向对象到SOA》正文及源码 &lt;/a&gt;&lt;/div&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p align="center"&gt;(http://files.cnblogs.com/bitfan/%e4%bb%8e%e9%9d%a2%e5%90%91%e5%af%b9%e8%b1%a1%e5%88%b0SOA.rar) &lt;br /&gt;&lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 以下是本文所附之示例源码的下载链接：&lt;/span&gt; &lt;/p&gt;  &lt;div align="center"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: medium;"&gt;&lt;a href="http://openapi.vdisk.me/open_file/31317c31323938373033/11adc2492dd1601acad6d2bd82bfec02/DealWithTCPBufferSourceCode.rar"&gt;示例源码下载链接&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="font-size: medium;"&gt; &lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/bitfan/aggbug/1938365.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bitfan/archive/2011/01/18/1938365.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bitfan/archive/2011/01/14/1935482.html</id><title type="text">一个多线程示例程序的BUG修复</title><summary type="text">一个多线程示例程序的BUG修复——《.NET 4.0面向对象编程漫谈 》勘误</summary><published>2011-01-14T05:41:00Z</published><updated>2011-01-14T05:41:00Z</updated><author><name>金旭亮</name><uri>http://www.cnblogs.com/bitfan/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bitfan/archive/2011/01/14/1935482.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bitfan/archive/2011/01/14/1935482.html"/><content type="html">&lt;div&gt;&lt;div align="center"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-size: x-large;"&gt; 一个多线程示例程序的BUG修复&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt; &lt;/span&gt;  &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 在《&lt;a href="http://blog.csdn.net/bitfan/archive/2010/11/06/5991783.aspx" target="_blank"&gt;.NET 4.0面向对象编程漫谈&lt;/a&gt; 》的《应用篇》一书中，我介绍了一个使用&amp;#8220;&lt;strong&gt;信号量（Semaphore）&lt;/strong&gt; &amp;#8221;同步对象模拟多人使用图书馆公共计算机的UseLibraryComputer示例（参看17.3.3节《管理多个共享资源--Semaphore》）：&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;div align="center"&gt;&lt;img src="http://hi.csdn.net/attachment/201101/14/0_1294982449y7q3.gif" alt="" /&gt;&lt;/div&gt; &lt;br /&gt; &amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;span style="font-size: small;"&gt; 图 1 UseLibraryComputer示例&lt;/span&gt;&lt;/div&gt;&lt;p&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 此示例程序定义了一个Computer类代表计算机，使用一个Computer对象数组（取名LibraryComputers）保存图书馆所拥有的多台公共计算机（即Computer对象）。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 示例程序动态创建多个线程模拟多用户（每个线程代表一个用户）同时访问3个Computer对象，为了同步这些线程，创建了一个Semaphore对象（取名sp），以下为示例中的线程函数：&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void UseComputer(Object UserName)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sp.WaitOne();//等待计算机可用&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //查找可用的计算机&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Computer cp=null;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; ComputerNum; i++)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (LibraryComputers[i].IsOccupied == false)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cp = LibraryComputers[i];&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //使用计算机工作&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cp.Use(UserName.ToString());&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //不再使用计算机，让出来给其他人使用&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sp.Release();&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; Computer类中定义了一个IsOccupied字段用于标识此计算机是否被占用，其Use方法模拟表示用户正在使用计算机的过程：&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; //是否被占用&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; public&amp;nbsp; bool IsOccupied = false;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; //读者在使用计算机&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; public&amp;nbsp; void Use(String userName)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("{0}开始使用计算机{1}", userName,ComputerName);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; IsOccupied = true;&amp;nbsp; //设置占用标记&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Thread.Sleep(new Random().Next(1, 2000)); //随机休眠，以模拟人使用计算机&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("{0}结束使用计算机{1}", userName,ComputerName);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; IsOccupied = false; //设置空闲标记&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 前述示例代码中隐藏着一个BUG，请看图2：&lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; &lt;/span&gt; &lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div align="center"&gt;&lt;img src="http://hi.csdn.net/attachment/201101/14/0_1294982564uU0U.gif" alt="" /&gt;&lt;/div&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;div align="center"&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;图 2&lt;/span&gt;&lt;/div&gt;&lt;p&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BUG隐藏于何处？&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 请读者先仔细阅读&lt;a href="http://openapi.vdisk.me/download_file/31317c31323431373930/a7fce339806a055e5c0bbb6e86e3ce6a/UseLibraryComputer.rar"&gt;原示例程序&lt;/a&gt; ，尝试着自己定位并修正此BUG。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 以下是BUG分析：&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 这里面的关键是Semaphore对象可能会一次允许多个线程投入运行，而这些投入运行的线程都需要访问LibraryComputers数组（请参看前面的UseComputer静态方法）。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 假设有3台计算机空闲，当示例程序第1次运行时，会有3个线程同时访问LibraryComputers数组，完全有可能两个线程都发现第1台计算机是&amp;#8220;空闲&amp;#8221;的，于是它们将调用此Computer对象的Use()方法。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 这就是BUG所在。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 定位BUG之后，要修正它就很容易了--&lt;span style="color: #993300;"&gt;&lt;strong&gt;互斥访问LibraryComputers数组即可&lt;/strong&gt; &lt;/span&gt; 。&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 修改后的线程函数如下：&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void UseComputer(Object UserName)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sp.WaitOne();//等待计算机可用&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Computer cp=null; //查找可用的计算机&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;span style="color: #993300;"&gt;lock (LibraryComputers)&lt;/span&gt; &lt;/strong&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; ComputerNum; i++)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (LibraryComputers[i].IsOccupied == false)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cp = LibraryComputers[i];&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;span style="color: #993300;"&gt;cp.IsOccupied = true;&amp;nbsp;&lt;/span&gt; &lt;/strong&gt;  //设置已被使用标记&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cp.Use(UserName.ToString());//使用计算机工作&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sp.Release();//不再使用计算机，让出来给其他人使用&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 注意：&lt;strong&gt;上述代码中不仅添加了锁，还将修改Computer对象占用标记的代码（原先在Computer.Use方法中）也移到这里来了。&lt;/strong&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 以下修改后的Computer.Use()方法：&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; public&amp;nbsp; void Use(String userName)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("{0}开始使用计算机{1}", userName,ComputerName);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Thread.Sleep(new Random().Next(1, 2000)); //随机休眠，以模拟人使用计算机&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("{0}结束使用计算机{1}", userName,ComputerName);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;span style="color: #993300;"&gt;IsOccupied = false;&amp;nbsp; &lt;/span&gt; &lt;/strong&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 最后留给读者一个思考题：&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #993300;"&gt;&lt;strong&gt;Computer.Use()方法中修改IsOccupied字段的那句代码需要锁定本对象吗？&lt;/strong&gt; &lt;/span&gt; &lt;/span&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; ============================================================================&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt; &lt;/p&gt; &lt;div align="center"&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;&lt;a target="_blank" href="http://dl.dbank.com/c027mdtcd9"&gt;点击下载本文示例源码&lt;/a&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://openapi.vdisk.me/download_file/31317c31323431373930/a7fce339806a055e5c0bbb6e86e3ce6a/UseLibraryComputer.rar"&gt;&lt;strong&gt; &lt;/strong&gt; &lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt; 附注：&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; 此示例程序中的BUG由CSDN网友&amp;#8220;&lt;a href="http://hi.csdn.net/space-2766398.html"&gt;笑傲江湖&lt;/a&gt; &amp;#8221;发现，是本人在设计示例时的疏漏，在此特别感谢&amp;#8220;笑傲江湖" 网友的热心！也欢迎各位读者或业界朋友多指正本人拙著中的错误，互相探讨技术，共同进步。&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/bitfan/aggbug/1935482.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bitfan/archive/2011/01/14/1935482.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bitfan/archive/2011/01/10/1931822.html</id><title type="text">《.NET 4.0网络开发入门之旅》6：“麻烦”的数据缓冲区</title><summary type="text">《.NET 4.0网络开发入门之旅》6：“麻烦”的数据缓冲区</summary><published>2011-01-10T04:05:00Z</published><updated>2011-01-10T04:05:00Z</updated><author><name>金旭亮</name><uri>http://www.cnblogs.com/bitfan/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bitfan/archive/2011/01/10/1931822.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bitfan/archive/2011/01/10/1931822.html"/><content type="html">&lt;div&gt;点击以下链接阅读本系列前面的文章：&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; 1. &lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/01/6047911.aspx"&gt;《开篇语&amp;#8212;&amp;#8212;&amp;nbsp; 无网不胜》&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; 2. &lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/06/6058227.aspx"&gt;《 IP知多少》&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; 3. 《&lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/10/6067800.aspx"&gt;我在&amp;#8220;网&amp;#8221; 中央&lt;/a&gt; 》 &lt;br /&gt;&amp;nbsp;&amp;nbsp; 4.《&lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/24/6097011.aspx"&gt;与Socket的第一次&amp;#8220;约会&amp;#8221;&lt;/a&gt;》&lt;/div&gt;&lt;p&gt;&lt;div&gt;&lt;a href="http://blog.csdn.net/bitfan/archive/2011/01/05/6118185.aspx"&gt;&amp;nbsp;&amp;nbsp; 5. 《与Socket的&amp;#8220;再次见面&amp;#8221;》&lt;/a&gt;&lt;/div&gt;&lt;div&gt;点击以下链接阅读《.NET 4.0网络开发入门之旅》的第6部分：&lt;/div&gt;&lt;p&gt;　&lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2011/01/10/6126536.aspx"&gt;6.《&amp;#8220;麻烦&amp;#8221;的数据缓冲区》 &lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;br /&gt;&lt;/p&gt;&amp;nbsp; 此文内容比较简单，恐怕不合园子里高手的口味，而且同一文章贴两遍麻烦，所以上述文章发在CSDN。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/bitfan/aggbug/1931822.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bitfan/archive/2011/01/10/1931822.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bitfan/archive/2011/01/05/1926451.html</id><title type="text">《.NET 4.0网络开发入门之旅》5：与Socket的“再次见面”</title><summary type="text">《.NET 4.0网络开发入门之旅》5：与Socket的“再次见面”</summary><published>2011-01-05T08:10:00Z</published><updated>2011-01-05T08:10:00Z</updated><author><name>金旭亮</name><uri>http://www.cnblogs.com/bitfan/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bitfan/archive/2011/01/05/1926451.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bitfan/archive/2011/01/05/1926451.html"/><content type="html">&lt;div&gt;&lt;span style="font-size: 18pt;"&gt;《.NET 4.0网络开发入门之旅》系列文章&lt;/span&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;点击以下链接阅读本系列前面的文章：&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; 1. &lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/01/6047911.aspx"&gt;《开篇语&amp;#8212;&amp;#8212;&amp;nbsp; 无网不胜》&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; 2. &lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/06/6058227.aspx"&gt;《 IP知多少》&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; 3. 《&lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/10/6067800.aspx"&gt;我在&amp;#8220;网&amp;#8221; 中央&lt;/a&gt; 》 &lt;br /&gt;&amp;nbsp;&amp;nbsp; 4 《&lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/24/6097011.aspx"&gt;与Socket的第一次&amp;#8220;约会&amp;#8221;&lt;/a&gt;》&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;点击以下链接阅读《.NET 4.0网络开发入门之旅》的第5部分：&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;span style="font-size: 14pt;"&gt;&lt;a href="http://blog.csdn.net/bitfan/archive/2011/01/05/6118185.aspx"&gt;5. 《与Socket的&amp;#8220;再次见面&amp;#8221;》&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&amp;nbsp;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp; 此文内容比较简单，恐怕不合园子里高手的口味，而且同一文章贴两遍麻烦，所以上述文章发在CSDN。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/bitfan/aggbug/1926451.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bitfan/archive/2011/01/05/1926451.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bitfan/archive/2010/12/30/1921291.html</id><title type="text">软件天才与技术民工</title><summary type="text">软件天才与技术民工——薛涌《天才是训练出来的》读后感</summary><published>2010-12-29T17:35:00Z</published><updated>2010-12-29T17:35:00Z</updated><author><name>金旭亮</name><uri>http://www.cnblogs.com/bitfan/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bitfan/archive/2010/12/30/1921291.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bitfan/archive/2010/12/30/1921291.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: x-large;"&gt;软件天才与技术民工&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: medium;"&gt;&amp;#8212;&amp;#8212;薛涌《天才是训练出来的》读后感&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: medium;"&gt;金旭亮&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 12pt;"&gt;长期以来，&amp;#8220;软件业&amp;#8221;一直被视为&amp;#8220;智力密集&amp;#8221;型的&amp;#8220;朝阳&amp;#8221;产业，大多数从业者都受过高等教育，其平均素质居于社会各行业的前列，这个产业的顶尖人物被公众视为&amp;#8220;知识英雄&amp;#8221;，比如微软公司的创始人比尔盖茨雄据世界首富之位多年，更是为人&amp;#8220;津津乐道&amp;#8221;。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 16年前我下决心开始学习计算机技术的时候，对这个行业也充满了自豪感。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然而世事难料，在2009年高考刚刚结束之际，中国权威出版机构社会科学文献出版社于2009年6月10日发布首部《中国大学毕业生就业报告（2009）》，其中&amp;#8220;计算机专业&amp;#8221;荣登 &amp;#8220;就业最困难的十大专业&amp;#8221;光荣榜。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 大约从2003年开始，我在北京理工大学这所211、985重点大学开设.NET课程，这件事后来给某些人&amp;#8220;炮轰&amp;#8221;--说我要将重点大学学生培养成IT民工，也曾有技术牛人谆谆教诲年青学生--想学软件，离金某人远些&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#8220;程序员&amp;#8221;何时变成了&amp;#8220;IT民工&amp;#8221;？ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 仅仅十多年，&amp;#8220;程序员&amp;#8221;就从&amp;#8220;精英&amp;#8221;沦落为&amp;#8220;民工&amp;#8221;，这也未免太戏剧性了吧！&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#8220;程序员&amp;#8221;真的是&amp;#8220;IT民工&amp;#8221;？&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在中国，不少程序员都是&amp;#8220;CRUD&amp;#8221;程序员，这不能怪他们，因为中国多数项目都是CRUD的。所以，CRUD似乎成为了&amp;#8220;IT民工&amp;#8221;身上的标签，问题是CRUD这活真的象在建筑工地上倒水泥一样，不需要太高的智商和较多的训练？&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下面分析一下需要从事这个CRUD的工作的程序员，到底需要哪些知识和技能。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我大致地思索了一下，画了以下这个图，展示出一名 &amp;#8220;.NET程序员民工&amp;#8221;要顺利参与一个CRUD的数据库应用项目开发所大致需要掌握的知识与技能：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/bitfan/CRUDApp.jpg" width="761" height="456" /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;图 1 &lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 12pt;"&gt;说句实话，这个图虽然&amp;#8220;挂一漏万&amp;#8221;，但列出来的知识点与需要掌握的技能之多已经很&amp;#8220;恐怖&amp;#8221;了，对于一个需要掌握这么多知识与技术才能胜任与干好的工作，非要认为它是一个&amp;#8220;低级&amp;#8221;的 &amp;#8220;民工&amp;#8221;就可以干的活，想必持这种观点的人一定知识丰富如汪洋大海，属&amp;#8220;白骨精（白领-骨干-精英）&amp;#8221;一族。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 需要掌握这么多的知识，才有资格当一名合格的&amp;#8220;CRUD&amp;#8221;程序员，&amp;#8220;IT民工&amp;#8221;的&amp;#8220;门槛&amp;#8221;其实挺高的，不是吗？&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 事实也如此，软件开发行业从业人员的平均学历我估计至少是大专，很可能是&amp;#8220;本科&amp;#8221;，其中固然有一些只有&amp;#8220;高中&amp;#8221;甚至更低学历的&amp;#8220;奇才&amp;#8221;，但这仅是少数，而且这些人，虽然学历低，但绝不会是一个低智商的人。这说明软件开发行业从业者的&amp;#8220;平均智商&amp;#8221;应该是挺高的。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我在旅美学者&lt;/span&gt;&lt;a href="http://blog.sina.com.cn/xueyong"&gt;&lt;span style="font-size: 12pt;"&gt;薛涌&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 12pt;"&gt;写的《天才是训练出来的》一书中找到了美国的一些统计数据：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #993300; font-size: 12pt;"&gt; 美国大学本科生的中等智商为118，学士学位获得者的中等智商为123，优秀毕业生的中等智商为133，物理学博士的平均智商为140。而在一般的人口中，中等智商为100。也就是说，你的智商如低于100分，你就属于偏笨的人，高于此线，就属于偏聪明的了。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 老外依据数据得出结论：&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;要把书读懂读好，智商还真的得达到一定的水准&lt;/strong&gt;。&lt;span style="font-size: 12pt;"&gt;所以，能上大学并且顺利拿到学位的人，基本上是属于比较聪明的那一批人。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们中国也有类似的观点，比如经常可以听到某家长叹息其小孩子成绩不好：我家的那个小祖宗，看来根本就不是读书的那块料！套用老外的观点，就是说这个小孩可能智商达不到上大学的基本要求。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 老外什么都喜欢数字化，所以动不动就来个什么&amp;#8220;智商&amp;#8221;测试，而中国虽然不讲智商这一套，但其实高考就可以看成是一次智商测试。在80、90年代，那时的大学生，经常都是百里挑一、几十里挑一，记得89年我参加高考，那年我们省的录取率还是十几取一。所以那个时代的大学生被称为&amp;#8220;天之娇子&amp;#8221;，并非&amp;#8220;空穴来风&amp;#8221;。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 重大的变化发生于1999年，从这一年开始中国大学开始扩招，尤其是计算机专业，更是扩招的重点，其规模迅速膨胀，录取率大大地提高，其结果是，用一句打趣的话说，&amp;#8220;阿猫阿狗都去读大学了&amp;#8221;，中国大学没有做智商测试的制度，不然，我想应该会看到21世纪在校大学生的平均智商比上世纪80、90年代的在校大学生的平均智商要低。但扩招对一些历史悠久声誉良好的重点大学的影响就没那么大，因为不管你怎么扩招，能进名校（比如北大清华）的学生，智商是不会低的，因为其入学竞争仍然十分激烈，各方面差一点的根本就没这个机会。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 老外还给出了一些著名科学家的智商：&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;牛顿190，伽利略195，开普勒175，达尔文165，哥白尼160。&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 12pt;"&gt; 我对这些数据抱有怀疑：牛顿和伽利略等的那个时代有智商测试吗？这些数据是从哪计算出来的？&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 但这些著名科学的智商高于普通人，我想不会有人怀疑。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 现在回到软件开发这个行业，其从业者平均学历为大专以上，应该说明这个行业需要的是整个人群中比较聪明的那一批。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个观点与我的实际感受是一致的。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我在IT业&amp;#8220;混&amp;#8221;了十多年，深感这个行业牛人辈出，别说这个行业的&amp;#8220;顶尖&amp;#8221;级别人物，就是在许多普通的IT企业、科研院所中，也有不少的让人佩服的牛人。我在北理工教了8年书，&amp;#8220;笨&amp;#8221;的学生实在没见着，而不少学生的聪明程度和学习能力等，都比我在他们这个年纪时要强得多，还有一些学生，真的很聪明，悟性好，能举一反三，在技术上没多久就可以跑到我前面去了。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所以，软件开发应该是一个需要有较高智商的行业，我觉得不会有太大疑义。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 为什么智商重要？我在薛涌 写的《天才是训练出来的》找到了以下描述：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #993300; font-size: 12pt;"&gt; 在美国的白人中，生于占人口5%的最低层的穷孩子，日后生活在贫困线以下的可能比那些生于占人口5%的最富裕阶层的孩子要高8倍。但是，那些智商属于最低的5%的孩子，则比那些智商属于最高的5%的孩子日后生活于贫困线以下的可能性高15倍。也就是说，你的脑子是否好使，比你的家庭是否富裕对你的未来重要得多。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 中国人有句俗话：三百六十行，行行出状元。这些&amp;#8220;状元&amp;#8221;的出身并不重要，但他们应该接近100%的都有高的智商。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 智商这个东西非常奇特，老外研究了这么多年，也没研究明白很多关键问题，比如智商是不是纯天生的？后天不能提高？如果能，那能提高多少？如何解释一些高智商的人一辈子成就平平？如何解释某些天才在某个领域内出类拔萃，在其他领域却连普通人都比不上？还有，更重要的一点：&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 普通人付出艰苦的努力，能成为天才吗？&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我不是心理学家，下面我仅就想针对软件开发来聊聊自己对这个问题的看法。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;span style="font-size: medium;"&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt; 你能成为软件天才吗？&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 12pt;"&gt; 在整个计算机领域，有一些老外的名字如雷贯耳：冯诺依曼，图灵，比尔盖茨、Anders Hejlsberg，在中国，诸如&amp;#8220;求伯君&amp;#8221;、&amp;#8220;柳传志&amp;#8221;、&amp;#8220;李开复&amp;#8221;等名人的故事也是众人皆知，虽然我们拿不到其智商测试的分数，但相信他们个个都是聪明人。&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong style="font-size: 12pt;"&gt;&amp;#8220;高智商&amp;#8221;其实是成为&amp;#8220;天才&amp;#8221;的必要条件。&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;相应的另一个结论就是：&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;普通人再怎么努力，也成不了天才。&lt;/strong&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这话看上去令人泄气，但这是客观事实。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 天才在各自领域内所达到的高度，大多数普通人是永远达不到的，比如如果有某人告诉我：你只要努力，就可以比Anders Hejlsberg还牛。我一定会认为他在开一个让我很生气的玩笑。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 回想起当年的高考，我费了九牛二虎之力，总分才刚够重点大学的最低分数线，后来的考研，我要考3次才侥幸过关，我也曾参过北大的博士生入学考试，结果惨败而回，以后知趣地不再尝试&amp;#8230;&amp;#8230;，我就这智商，普通人一个，所以您就别忽悠我了，我才不信天天坚持跑步，日后就可以参加奥运会的马拉松比赛呢！&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;个体间智商的差异是客观存在的。&lt;/strong&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 但成为不了天才不能成为躺倒不干的理由。因为这里有一个引发了巨大争论的问题&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;strong&gt;&lt;span style="font-size: large;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 智商重要还是努力重要？&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 12pt;"&gt; 国外心理学的统计数据明确无误地说明了智商的重要性，但这里有一个问题：就算是具有&amp;#8220;天才&amp;#8221;浅质的人在总人员的比例很少，但人类有数十亿之多，&amp;#8220;天才&amp;#8221;应该不少啊？怎么数千年来，公认 &amp;#8220;天才&amp;#8221;的就是牛顿等那几个？&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1973年，诺贝尔经济学奖得主、人工智能研究的开拓者Herbert Simon和William Chase在研究国际象棋大师的成长规律时发现：再大的天才，也需要10年修炼成器。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 音乐天才莫扎特似乎打破了这个&amp;#8220;十年定律&amp;#8221;。5岁做曲，10岁登台演出，一生创作了数百部传世之作。尽管如此，西方学者们还是发现，莫扎特6岁时就已经和父亲一起训练了3500个小时，他第一部达到大师水平的作品，创作年纪是21岁，实际上已经经历了18年的严格训练。&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;span style="color: #993300; font-size: 12pt;"&gt;聪明的脑瓜是必要的，但仅有它也是不够的。&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我引用了这么多的资料，其实只为了说明一个结果：&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 不经&amp;#8220;十年寒窗&amp;#8221;，&amp;#8220;天才&amp;#8221;不可能出来。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 本身具有高智商的人是这样，在平均智商上下的人更应该努力。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 现在很好解释当下的一些现象了：&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; （1）&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;&amp;#8220;程序员&amp;#8221;为何是&amp;#8220;IT民工&amp;#8221;？&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;因为这些所谓的&amp;#8220;程序员&amp;#8221;本身就没有具备从事软件开发的基本知识与基本技能，加上人数众多，可替换性强，怎么会不成为&amp;#8220;IT民工&amp;#8221;？&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; （2）&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;计算机专业学生为何就业难？&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;很简单，一个计算机专业本科生，四年下来至少应该有4~6万行的代码量，但就我观察，达到这个要求的不到10%。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 尽管软件开发行业需要较高的智商，但在平均学历为本科的软件开发行业，从业者已经过高考的筛选，智商并不是问题关键，之所以&amp;#8220;IT民工&amp;#8221;多和计算机专业学生就业难，主要问题是&amp;#8220;&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;懒&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;&amp;#8221;和&amp;#8220;&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;训练不得法&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;&amp;#8221;。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下图是我总结的一个靠技术吃饭的&amp;#8220;程序员&amp;#8221;知识与能力增长路线图：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/bitfan/Life.jpg" width="745" height="602" /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;图 2 &lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 12pt;"&gt;这个图不是针对&amp;#8220;天才&amp;#8221;设计的，而是针对一个&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;普通&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;的计算机专业大学生可能的主要人生经历绘制的，虽然经过了大量的简化，但主线还是很清楚的。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;span style="font-size: large;"&gt;我成不了天才，那成为&amp;#8220;人材&amp;#8221;，可以吗？&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 12pt;"&gt;对这个问题，我的观点和薛涌先生在《天才是训练出来的》这本书中所表达的观点是一致的：&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong style="font-size: 12pt;"&gt;完全可以。&lt;/strong&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们需要解决的问题是&amp;#8220;如何努力&amp;#8221;的问题。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 薛涌先生在书中介绍了一种名为&amp;#8220;&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;处心积虑的训练（deliberation practice）&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;&amp;#8221;的天才训练方法，这种方法是由天才研究的权威人士Ericsson教授提出的，简称为&amp;#8220;&lt;/span&gt;&lt;span style="color: #993300; font-size: 12pt;"&gt;&lt;strong&gt;深练（deep practice）&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-size: 12pt;"&gt;&amp;#8221;，其意思是一般人练得浅，水平自然平庸，天才则练得深，所以能超出凡人之上。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 普通人如果能科学地深练，虽然不能成为天才，但成为&amp;#8220;半个&amp;#8221;天才是完全可能的。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 有关&amp;#8220;深练&amp;#8221;的介绍，朋友们可以自行去看《天才是训练出来的》这本书。就我多年自学软件技术和8年的教学经验，我并不觉得&amp;#8220;深练&amp;#8221;有何奇特之处，我将&amp;#8220;深练&amp;#8221;总结为以下几句话：&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; （1）&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;织网&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;：分解软件技术的大块知识为多个小的知识点，各个击破，将新知识与老知识联系起来，构造一张完整的可动态扩充的知识之网&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; （2）&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;训练&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;：将开发技能给拆分为多个小的步骤或子技能，针对每个步骤或子技能反复地严格地训练，然后再这些步骤或子技能组合起来，以达到职业的水准。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; （3）&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;探究性的学习与实践&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;：要将被动的学习转换为主动的探索，要通过开发实践把一切给&amp;#8220;激活&amp;#8221;。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我写了不少文章表达过自己针对软件技术学习的看法，在个人所写的几本书的前言中也比较系统地表达过类似的观点，这里就不再重复了，这些文章在我的&lt;/span&gt;&lt;a style="font-size: 12pt;" href="http://blog.csdn.net/bitfan"&gt;个人博客&lt;/a&gt;&lt;span style="font-size: 12pt;"&gt;上都可以找到。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 而我也将在日后的开发与教学实践中应用这些原则，探索更有效的学习与训练方法。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下面，我们来看另一个很困扰人的问题：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;&lt;span style="font-size: large;"&gt;我是知道我成不了天才，但为何我也没成&amp;#8220;人材&amp;#8221;？我可从没偷懒过啊！&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="font-size: 12pt;"&gt;这个问题太有中国特色了！这里面关键有几点：&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: 12pt;"&gt;（1）&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;你错过了&amp;#8220;学习天窗&amp;#8221;&lt;/strong&gt;。&lt;span style="font-size: 12pt;"&gt;任何一种知识和技能，都有学习与培养它的最佳时间段，我们将它称为&amp;#8220;学习天窗&amp;#8221;，比如一个两三岁的小孩子可以轻而易举地学会两三种语言，而且不会有口音，而一个成人就够呛了，以英语为例，我们都受够了难听无比的&amp;#8220;日本英语&amp;#8221;和&amp;#8220;印度英语&amp;#8221;，&amp;#8220;中国英语&amp;#8221;也好不到哪去。拿软件技术而言，最佳的学习时间是大学的这几年，18岁~25岁左右，精力、体力、智力，无不处于高峰，你这时不学，拿这个时间去玩游戏，看大片，QQ海聊，上网乱逛&amp;#8230;&amp;#8230;，等到30岁以后再学，会发现你花3个小时才能记住的东西，10年以前可能1.5个小时（甚至更少的时间）就能记住了。后悔也晚了。这也只能怪你自己。&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong style="font-size: 12pt;"&gt;（2）命运：&lt;/strong&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;&lt;span style="color: #993300;"&gt;&amp;nbsp; 幸运的是，你生在中国！&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;你没生在阿富汗和非洲，那里天天子弹飞，饿肚子，闹瘟疫，这种环境下你还能学计算机，编程序？&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #993300; font-size: 12pt;"&gt;&lt;strong&gt; 倒霉的是，你也生在中国！&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-size: 12pt;"&gt;如果你生在美国，你就可以摆脱那因为千军万马过独木桥而喘不过气来的中小学应试体制，上了大学，也可以得到比较好的专业引导和教育，避开那因为&amp;#8220;行政化&amp;#8221;而&amp;#8220;弊端从生&amp;#8221;的中国高等教育体制。中国这个大环境你个人是改不了的。&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #993300; font-size: 12pt;"&gt;&lt;strong&gt; 最倒霉的是，你不仅生在中国，而且你爸不是李刚&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-size: 12pt;"&gt;，&lt;/span&gt;&lt;strong style="font-size: 12pt;"&gt;&lt;span style="color: #993300;"&gt;你家在很远的地方，那地方很穷，&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-size: 12pt;"&gt;家里买不起电脑，更别说上网了，你可能要到大学才第一次接触到电脑&amp;#8230;&amp;#8230;，让你雪上加霜的是：你竞争不过那些学习条件好的同学，虽然你不笨，也很努力，但在起点就落后了，结果你没上到好大学，没碰到好老师，一步晚，步步晚&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;br style="font-size: 12pt;" /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这不是你的责任，真的，不是你的责任！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp; &amp;nbsp; 但不要追问是谁的责任。&amp;nbsp; &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 再追问下去，你可能就要去宗教中寻找归宿了。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 路在何方？&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 你手上抓的牌不太好，这没办法，这是命运问题，这世界本来就是不公平的，老子说过：天地不仁，以万物为刍狗&amp;#8230;&amp;#8230;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 别想那么多了，不抱怨不等待，积极努力，想办法把手头抓的这副&amp;#8220;坏牌&amp;#8221;打好，这是最现实最正确的选择。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 只要个人努力了，其他的丢给命运吧！你还能怎的？&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/bitfan/aggbug/1921291.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bitfan/archive/2010/12/30/1921291.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bitfan/archive/2010/12/25/1916570.html</id><title type="text">《.NET 4.0网络开发入门之旅》4：与Socket的第一次“约会”</title><summary type="text">《.NET 4.0网络开发入门之旅》4：与Socket的第一次“约会”</summary><published>2010-12-25T02:42:00Z</published><updated>2010-12-25T02:42:00Z</updated><author><name>金旭亮</name><uri>http://www.cnblogs.com/bitfan/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bitfan/archive/2010/12/25/1916570.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bitfan/archive/2010/12/25/1916570.html"/><content type="html">&lt;div&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="font-size: 18pt;"&gt;《.NET 4.0网络开发入门之旅》系列文章&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;点击以下链接阅读本系列前面的文章：&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; 1. &lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/01/6047911.aspx"&gt;《开篇语&amp;#8212;&amp;#8212;&amp;nbsp; 无网不胜》&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; 2. &lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/06/6058227.aspx"&gt;《 IP知多少》&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; 3. 《&lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/10/6067800.aspx"&gt;我在&amp;#8220;网&amp;#8221; 中央&lt;/a&gt; 》 &lt;br /&gt;&lt;br /&gt;点击以下链接阅读《.NET 4.0网络开发入门之旅》的第4部分：&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4 《&lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/12/24/6097011.aspx"&gt;与Socket的第一次&amp;#8220;约会&amp;#8221;&lt;/a&gt;》&lt;br /&gt;&lt;br /&gt;&amp;nbsp;此文内容比较简单，恐怕不合园子里高手的口味，而且同一文章贴两遍麻烦，所以上述文章发在CSDN。&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/bitfan/aggbug/1916570.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bitfan/archive/2010/12/25/1916570.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bitfan/archive/2010/12/10/1902271.html</id><title type="text">.NET 4.0网络开发入门之旅——我在“网” 中央（下）</title><summary type="text">.NET 4.0网络开发入门之旅——我在“网” 中央（下）</summary><published>2010-12-10T06:28:00Z</published><updated>2010-12-10T06:28:00Z</updated><author><name>金旭亮</name><uri>http://www.cnblogs.com/bitfan/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bitfan/archive/2010/12/10/1902271.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bitfan/archive/2010/12/10/1902271.html"/><content type="html">&lt;div&gt;&lt;span style="font-size: 14pt;"&gt;.NET 4.0网络开发入门之旅--&lt;/span&gt;&lt;br /&gt;&lt;div align="center"&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 24pt;"&gt; &amp;nbsp;我在&amp;#8220;网&amp;#8221; 中央（下）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p align="center"&gt;续上篇《&lt;a target="_blank" href="http://www.cnblogs.com/bitfan/archive/2010/12/10/1902257.html"&gt;.NET 4.0网络开发入门之旅&amp;#8212;&amp;#8212;我在&amp;#8220;网&amp;#8221; 中央（上）&lt;/a&gt;》&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;strong&gt;&lt;span style="font-size: 14pt;"&gt;4 我&amp;#8220;连网&amp;#8221;了吗？&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;/div&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 好了，有了前面的铺垫，现在解决判断计算机连网问题水到渠成，其思路很简单：&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;（1）检测一下计算机中的所有网络接口状态，只要都为&amp;#8220;Down&amp;#8221;，没说的，肯定没连网。&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;（2）从状态为&amp;#8220;Up&amp;#8221;的网络接口中选一个（注意排除掉环回接口Loopback），获取其网关和DNS服务器地址，先Ping一下它的网关，如果能Ping通，再Ping一下DNS服务器，看看能不能Ping通。&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;如果网关Ping不通，就换一个&amp;#8220;Up&amp;#8221;的网络接口试一试，重复上述过程，直到检测完了所有&amp;#8220;Up&amp;#8221;的网络接口。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;现在结果呼之欲出了：&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;（1）只要有一个网络接口可以Ping通网关，则&amp;#8220;本计算机肯定已连上本地网络。&amp;#8221;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;（2）只要有一个网络接口可以Ping通DNS，则&amp;#8220;本计算机的本地网络设置没有问题。&amp;#8221;除非DNS服务器本身故障（应该发生机率不高）或由于你欠费之类的账号被限制，则&amp;#8220;本计算机联上互联网应该没问题&amp;#8221;。&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;（3）为了真正确认已联上互联网，Ping一个&amp;#8220;Well-Known&amp;#8221;的网址，比如&amp;#8220;百度&amp;#8221;，能Ping通则100%确信可以上网了。&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span style="color: #993300;"&gt;注意：&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #993300;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;某些网站不响应Ping数据包，比如笔者发现微软公司主机就不理会Ping数据包，对其主机的Ping操作将以&amp;#8220;超时（TimeOut）&amp;#8221;收场。&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;有的朋友看到这里，不禁会说：&lt;br /&gt;&lt;strong&gt;&lt;span style="color: #993300;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style="color: #993300;"&gt;你这不是多此一举了吗？一上来直接Ping一个互联网主机，不就知道能不能上网了吗？&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;呵呵，这怎么说呢？不能上网的原因太多了，如果你的网络应用程序能告之用户更详细的信息：&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;无法连接网关，请检查你的网络设置&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;无法连接DNS服务器，您所指定的DNS服务地址&amp;#8220;192.168.1.1&amp;#8221;可能有误，或者是DNS服务器故障&amp;#8230;&amp;#8230;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;是不是更有助于用户定位网络问题？&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;我在示例程序中写了一个IsOnline方法实现了前述的连网检测逻辑：&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('699334da-76e6-4c4a-80e2-725d613a42f8')"&gt;&lt;img src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" class="code_img_closed" id="code_img_closed_699334da-76e6-4c4a-80e2-725d613a42f8" style="display: none;" alt="" /&gt;&lt;img src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" class="code_img_opened" id="code_img_opened_699334da-76e6-4c4a-80e2-725d613a42f8" onclick="cnblogs_code_hide('699334da-76e6-4c4a-80e2-725d613a42f8',event)"&gt;&lt;div id="cnblogs_code_open_699334da-76e6-4c4a-80e2-725d613a42f8"&gt;&lt;div&gt;&lt;!--&lt;br/&gt;&lt;br/&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/&gt;http://www.CodeHighlighter.com/&lt;br/&gt;&lt;br/&gt;--&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IsOnline()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(NetworkInterface.GetIsNetworkAvailable()&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;所有网卡都是&amp;#8220;Dwon&amp;#8221;的&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;选出&amp;#8220;Up&amp;#8221;的网卡，并且排除掉环回接口&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;query&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;from&amp;nbsp;nic&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;in&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;NetworkInterface.GetAllNetworkInterfaces()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;where&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;nic.OperationalStatus&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;OperationalStatus.Up&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nic.NetworkInterfaceType&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;NetworkInterfaceType.Loopback&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;select&amp;nbsp;nic;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(var&amp;nbsp;nic&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;in&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;query)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;先Ping网关&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Ping&amp;nbsp;pinger&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Ping();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;GatewayReady&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(GatewayIPAddressInformation&amp;nbsp;GatewayAddr&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;in&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nic.GetIPProperties().GatewayAddresses)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PingReply&amp;nbsp;reply&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;pinger.Send(GatewayAddr.Address);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(reply.Status&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPStatus.Success)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;GatewayReady&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(GatewayReady&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;continue&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;所有网关都不通，不再进行下一步测试，直接检测下一个网卡&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;网关Ping通了，可以Ping&amp;nbsp;DNS&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(IPAddress&amp;nbsp;addr&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;in&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;nic.GetIPProperties().DnsAddresses)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PingReply&amp;nbsp;reply&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;pinger.Send(addr);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(reply.Status&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPStatus.Success)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;上述代码中除了没有完成Ping一个&amp;#8220;Well-Known&amp;#8221;的真实互联网之外，其余的工作都已完成。&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;IsOnLine方法返回&amp;#8220;True&amp;#8221;时，表示本地网络可以Ping通DNS，否则，返回&amp;#8220;False&amp;#8221;，你可以修改这个方法，让其依据具体情况返回更详细的信息（比如是哪个网卡的网关还是DNS不能Ping通）。&lt;br /&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14pt;"&gt;&amp;nbsp; &amp;nbsp;5 让我们&amp;#8220;并行&amp;#8221;起来！&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 现在再来一点&amp;#8220;Cool&amp;#8221;的。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;仔细考虑一下我们的&amp;#8220;连网&amp;#8221;判断逻辑，不难发现这些Ping操作是可以并行执行的，如果能使用多个线程同时执行Ping操作，无疑可以减少得到&amp;#8220;是否可以访问互联网&amp;#8221;这一最终结论的时间。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;我们可以将IsOneLine方法转换为多线程版。&lt;br /&gt;&lt;span style="color: #993300;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #993300;"&gt;使用独立的线程执行每个网络接口的Ping操作，必须等待Ping网关的线程执行结束之后，依据其执行结果再决定是否新开一个线程执行Ping DNS的操作。&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #993300;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;当有一个网卡可以Ping通DNS时，应该通知其它线程停止工作，因为&amp;#8220;能否上网&amp;#8221;的结论已经得出了。&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里面其实涉及到不少比较复杂的线程同步问题，需要用到多个线程同步对象，并且还涉及到如何中途取消一个线程执行的问题，我在《&lt;a target="_blank" href="http://blog.csdn.net/bitfan/archive/2010/11/06/5991783.aspx"&gt;.NET 4.0面向对象编程漫谈&lt;/a&gt;》的《应用篇》中，花了100多页的篇幅讲多线程，其中介绍了.NET 4.0基类库中几乎所有的线程同步对象的用法，并大力推荐推荐使用.NET 4.0的&amp;#8220;线程统一取消模型&amp;#8221;（参看《应用篇》的16.5 《线程统一取消模型》）来中途取消一个线程的执行。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;读者您能否将IsOneLine方法转换为多线程版，是一块检测您是否真正掌握了多线程技术的试金石。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;在这里，我想向读者介绍如何直接使用TPL（任务并行库）而不是线程达到目的。 &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;需要仔细分析一下IsOnLine的处理逻辑，看看哪些部分是可以并行的，这些并行操作间有怎样的合作关系。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;很明显，对于多个网络接口的连接检测工作完全是可以并行的，这是第一个任务并行点。&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;其次，一个网络接口一般只有一个网关，不需要并行，但一个网络接口可能会有两个以上的DNS服务地址，很明显，这是第二个任务并行点。&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;第三，在同时运行的多个并行任务之间，任何一个得到&amp;#8220;互联网可达&amp;#8221;最终结果的并行任务，需要通知其他任务提前中止执行。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;经过以上考虑，使用并行循环（Parallel.ForEach）而不是Task对象是更合理的选择。Parallel.ForEach可以并行执行一个循环，并且通过ParallelLoopState对象可以提前中止循环，还可以&amp;#8220;通知到&amp;#8221;其他工作线程。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;以下是使用任务并行库实现的IsOnLine版本：&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('12cfd9e0-f5e2-486d-85f6-394bceb143c3')"&gt;&lt;img src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" class="code_img_closed" id="code_img_closed_12cfd9e0-f5e2-486d-85f6-394bceb143c3" style="display: none;" alt="" /&gt;&lt;img src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" class="code_img_opened" id="code_img_opened_12cfd9e0-f5e2-486d-85f6-394bceb143c3" onclick="cnblogs_code_hide('12cfd9e0-f5e2-486d-85f6-394bceb143c3',event)"&gt;&lt;div id="cnblogs_code_open_12cfd9e0-f5e2-486d-85f6-394bceb143c3"&gt;&lt;div&gt;&lt;!--&lt;br/&gt;&lt;br/&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/&gt;http://www.CodeHighlighter.com/&lt;br/&gt;&lt;br/&gt;--&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IsOnlineUseTPL()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(NetworkInterface.GetIsNetworkAvailable()&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;选出所有处于激活状态的网卡&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;query&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;from&amp;nbsp;nic&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;in&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;NetworkInterface.GetAllNetworkInterfaces()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;where&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;nic.OperationalStatus&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;OperationalStatus.Up&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nic.NetworkInterfaceType&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;NetworkInterfaceType.Loopback&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;select&amp;nbsp;nic;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;NicReady&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;当有一个网卡的DNS是可达时，此值会大于0.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;以下开始定义可并行的任务，针对每个网络接口的&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Action&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;NetworkInterface,&amp;nbsp;ParallelLoopState&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;PingNetworkInterface&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(nic,&amp;nbsp;outState)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Ping&amp;nbsp;pinger&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Ping();&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;Ping网关&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;GatewayReady&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(GatewayIPAddressInformation&amp;nbsp;GatewayAddr&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;in&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nic.GetIPProperties().GatewayAddresses)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(outState.IsStopped)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;其他网卡的Ping循环已被中止&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PingReply&amp;nbsp;reply&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;pinger.Send(GatewayAddr.Address);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(reply.Status&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPStatus.Success)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;GatewayReady&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(GatewayReady&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;网关的都Ping不通，不必再Ping&amp;nbsp;DNS了&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;结束本网卡的Ping工作&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;网关是通的，就可并行Ping所有DNS地址&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;span style="color: red;"&gt;Parallel.ForEach&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: #000000;"&gt;(nic.GetIPProperties().DnsAddresses,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(dnsaddr,&amp;nbsp;innerState)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;其他Ping循环（本网卡的或者是其它网卡的）已被中止&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(innerState.IsStopped&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;||&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;outState.IsStopped)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ping&amp;nbsp;pinger2&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Ping();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PingReply&amp;nbsp;reply&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;pinger2.Send(dnsaddr);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(reply.Status&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPStatus.Success)&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;Ping成功&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;表明此网卡DNS可达&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;span style="color: red;"&gt;&amp;nbsp;Interlocked.Increment(&lt;/span&gt;&lt;span style="color: red;"&gt;ref&lt;/span&gt;&lt;span style="color: red;"&gt;&amp;nbsp;NicReady);&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;不需要再进行本并行循环的后继的循环工作&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;innerState.Stop();&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;outState.Stop();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;上层的并行循环也可以中止了&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;并行任务定义结束&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;执行并行任务&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;span style="color: red;"&gt;&amp;nbsp;Parallel.ForEach&lt;/span&gt;&lt;/strong&gt;&lt;span style="color: #000000;"&gt;(query,&amp;nbsp;PingNetworkInterface);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;NicReady&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;上述代码比较长，用到了一些比较复杂的编程特性，比如&amp;#8220;LINQ查询&amp;#8221;、&amp;#8220;Lambda&amp;#8221;表达式，Parallel并行循环等。请读者先仔细阅读《.NET 4.0面向对象编程漫谈》的以下章节扫清知识障碍，再通过阅读代码中的注释，并在Visual Studio中进行调试才能看懂这些代码：&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;8.4节《 匿名方法与Lambda表达式》&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;11.5节《掌握LINQ查询表达式的编写技巧》&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;17.2.3节《实现原子操作--Interlocked》&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;19.3.3节《使用Parallel类编写并行代码》&lt;/li&gt;&lt;li&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;19.3.9 节《并行任务的取消》&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;如果希望将并行版本的IsOnlineTPL用于有可视化界面的程序，推荐创建一个新的背景线程执行此方法，然后使用第18章《跨线程访问可视化控件》所介绍的方法将结果&amp;#8220;推送&amp;#8221;到UI线程中，更新可视化界面（比如就象Windows一样切换显示图片）。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;另外，.NET基类库中有一个NetworkChange密封类，当用户计算机的IP地址改变时（包括用户手动更改的，或者是用户关闭了无线功能等间接原因造成）它可以引发一个NetworkAddressChanged事件，可以在此事件中调用IsOnlineTPL方法重新检测是否网络可达。&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: 14pt;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;6 小结&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp;由于我的网络环境比较单一，所以没法测试IsOnlineTPL方法是否可以在各种各样的网络环境下正常工作，另外，此方法仅仅检测到DNS是否&amp;#8220;通&amp;#8221;为止，并没有去Ping一个真正的&amp;#8220;互联网主机&amp;#8221;，而且有些网络主机可能不理会&amp;#8220;Ping&amp;#8221;操作发出的数据包，因此，IsOnlineTPL返回false并不一定意味着网络不可达。读者大可以在我的代码的基础上进行完善，或者是设计一个新的更好的实现方案。&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;本文仅起一个抛砖引玉的工作，如有错误，敬请朋友们回贴指出，不胜感激！&lt;br /&gt;=======================================&lt;br /&gt;&lt;/p&gt;&lt;p align="center"&gt;&amp;nbsp;&lt;a href="http://files.cnblogs.com/bitfan/IsOnLine.rar"&gt;&lt;span style="font-size: 14pt;"&gt;点击下载本文所关联的示例源码&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;预告：&lt;/p&gt;&lt;p&gt;在后面的文章中，.NET网络开发的主角&amp;#8212;&amp;#8212;Socket 将正式登场！&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&amp;nbsp;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/bitfan/aggbug/1902271.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bitfan/archive/2010/12/10/1902271.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
