﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-懒人居</title><link>http://www.cnblogs.com/Alexander-Lee/</link><description>要生猛的面对生活</description><language>zh-cn</language><lastBuildDate>Wed, 10 Feb 2010 08:35:54 GMT</lastBuildDate><pubDate>Wed, 10 Feb 2010 08:35:54 GMT</pubDate><ttl>60</ttl><item><title>程序猿的小说阅读器</title><link>http://www.cnblogs.com/Alexander-Lee/archive/2010/01/20/txtbookreader.html</link><dc:creator>亚历山大同志</dc:creator><author>亚历山大同志</author><pubDate>Wed, 20 Jan 2010 08:57:00 GMT</pubDate><guid>http://www.cnblogs.com/Alexander-Lee/archive/2010/01/20/txtbookreader.html</guid><description><![CDATA[<p>阅读: 2216 评论: 28 作者: <a href="http://www.cnblogs.com/Alexander-Lee/" target="_blank">亚历山大同志</a> 发表于 2010-01-20 16:57 <a href="http://www.cnblogs.com/Alexander-Lee/archive/2010/01/20/txtbookreader.html" target="_blank">原文链接</a></p><p>&nbsp;</p>
<p>半夜看小说突发灵感，遂谋杀时间2H，搞定小程序一个-程序猿专用小说阅读器</p>
<p>引用发在codeplex上的项目介绍就是</p>
<p>&nbsp;</p>
<fieldset><legend>引用</legend><strong>Project Description</strong><br />
这是一个邪恶的程序，其用途是用于程序员在上班的时候神不知鬼不觉的看txt小说......<br />
<br />
为了达到神不知鬼不觉的目的，本程序被设计为一个console应用程序，并且设置了boss键，一按下后就会在console里print出大堆的貌似trace log的东西，让boss误认为你是在辛勤的工作.....<br />
<br />
本程序没有任何配置，因为有源代码，作者认为作为一个合格的程序员，你可以自己修改之，如果做不到，还是上班老实工作的好，不要浪费时间看小说了<br />
</fieldset>
<p>&nbsp;</p><p>项目地址：http://ptxtreader.codeplex.com/ <br /></p><p>希望大家都check out代码修改或者做一个更好用的，不要直接下载exe文件用现成。</p><p>&nbsp;</p><p>无耻的发一下首页，并调查一下，上班看小说的人举手，谢谢 <br /></p><img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1652545.html?type=1" width="1" height="1" alt=""/><p>评论: 28　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2010/01/20/txtbookreader.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2010/01/20/txtbookreader.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56855/" target="_blank">NDepend 3.0已与Visual Studio集成</a><span style="color:gray">(2010-02-10 16:17)</span><br/>· <a href="http://news.cnblogs.com/n/56854/" target="_blank">Ruby in Steel 1.5发布，去除IronRuby支持</a><span style="color:gray">(2010-02-10 16:14)</span><br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>装修月记第一弹，硬装篇</title><link>http://www.cnblogs.com/Alexander-Lee/archive/2009/12/21/1628899.html</link><dc:creator>亚历山大同志</dc:creator><author>亚历山大同志</author><pubDate>Mon, 21 Dec 2009 07:13:00 GMT</pubDate><guid>http://www.cnblogs.com/Alexander-Lee/archive/2009/12/21/1628899.html</guid><description><![CDATA[<p>阅读: 310 评论: 7 作者: <a href="http://www.cnblogs.com/Alexander-Lee/" target="_blank">亚历山大同志</a> 发表于 2009-12-21 15:13 <a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/12/21/1628899.html" target="_blank">原文链接</a></p><p>硬装完成进入配饰阶段，特此记录。</p>  <p>房屋位置：</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_2.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="119" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb.png" width="244" border="0" /></a> </p>  <p>首先是入户这个地方，由于没有设计生活阳台（靠，有入户没生活阳台，有生活阳台没入户，真是很FT，FT的蓝光）所以热水器和气表放在了这里，我打算做个什么把他们挡起来，不过通气前暂时没有办法了。很丑</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_4.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_1.png" width="173" border="0" /></a> 后边的是鞋柜，从这里可以看出来我用了安信的地板，实木复合</p>  <p>一进门最显眼的其实是入户的地面，火山岩的马赛克，真是很昂啊</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_6.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_2.png" width="174" border="0" /></a> </p>  <p>再一抬眼就能看到很骚包的酒红色烤瓷面板橱柜了，为了骚包的酒红色烤瓷又是1W多的开销</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_8.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_3.png" width="167" border="0" /></a> 进屋换个角度后<a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_10.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_4.png" width="160" border="0" /></a> </p>  <p>厨房的集成吊顶</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_12.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="172" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_5.png" width="244" border="0" /></a> 过了厨房就进入了客厅</p>  <p>客厅里最骚包的水晶灯还没装，就只能看见为了配合水晶灯的雕花</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_14.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="264" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_6.png" width="414" border="0" /></a> </p>  <p>换个角度再看看</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_16.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_7.png" width="204" border="0" /></a> 这里也能看出沙发的背景墙是分色喷得，不过灯太暗看不出很明显。</p>  <p>客厅的地板-安信复合实木，从客厅到卧室全铺</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_18.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="161" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_8.png" width="244" border="0" /></a> </p>  <p>位于阳台的大储物柜</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_20.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_9.png" width="160" border="0" /></a> 主卧的大衣柜<a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_22.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_10.png" width="162" border="0" /></a></p>  <p>次卧的衣柜</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_24.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_11.png" width="162" border="0" /></a>&#160; 主卧外的衣柜 <a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_26.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_12.png" width="156" border="0" /></a>&#160; </p>  <p>主卧的灯带和射灯</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_28.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_13.png" width="175" border="0" /></a> 主卧走廊的射灯 <a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_30.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_14.png" width="150" border="0" /></a> </p>  <p>&#160;</p>  <p>最骚包的厕所，流水马赛克，边上也是玻璃马赛克</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_32.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_15.png" width="162" border="0" /></a>&#160; 从里边看出来 <a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_34.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_16.png" width="162" border="0" /></a> </p>  <p>&#160;</p>  <p>最后就是家里的开关了，开关和插座全换过了，插座全是TCL的，不过外边的开关是液晶触摸开关，又是个骚包的东西</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_36.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="166" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_17.png" width="244" border="0" /></a> 门口的开关<a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_38.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="202" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/beecbb0b8722_CDC9/image_thumb_18.png" width="244" border="0" /></a> </p>  <p>可以看出来图案是我自己画O(∩_∩)O哈哈~</p>  <p>&#160;</p>  <p>后记，马上做开荒，等装了配饰和家具后再发下篇，呵呵</p><img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1628899.html?type=1" width="1" height="1" alt=""/><p>评论: 7　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/12/21/1628899.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/12/21/1628899.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56855/" target="_blank">NDepend 3.0已与Visual Studio集成</a><span style="color:gray">(2010-02-10 16:17)</span><br/>· <a href="http://news.cnblogs.com/n/56854/" target="_blank">Ruby in Steel 1.5发布，去除IronRuby支持</a><span style="color:gray">(2010-02-10 16:14)</span><br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>也就说说异常那些事儿</title><link>http://www.cnblogs.com/Alexander-Lee/archive/2009/12/18/1627105.html</link><dc:creator>亚历山大同志</dc:creator><author>亚历山大同志</author><pubDate>Fri, 18 Dec 2009 05:16:00 GMT</pubDate><guid>http://www.cnblogs.com/Alexander-Lee/archive/2009/12/18/1627105.html</guid><description><![CDATA[<p>阅读: 2073 评论: 34 作者: <a href="http://www.cnblogs.com/Alexander-Lee/" target="_blank">亚历山大同志</a> 发表于 2009-12-18 13:16 <a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/12/18/1627105.html" target="_blank">原文链接</a></p><h1>前言</h1>  <p>首先本文的阐述源于本人自身对异常的理解，以及总结归纳自身实践以及网络所带来经验。</p>  <p>其次是本文的目的，源于<a href="http://www.cnblogs.com/wlb/archive/2009/12/18/1626816.html">再次探讨企业级开发中的Try......Catch性能问题</a> 一文，我对此文的实践结果无异议，但是其立论实在值得商榷，故书此文共同探讨之。</p>  <h1>何谓异常</h1>  <p>很多人在讨论异常的时候很模糊，仿佛所谓异常就是try{}catch{}，异常就是Exception，非常的片面，所以导致异常影响性能，XXXX……等很多奇怪的言论，所以在此我意在对异常正名。以下，我将异常这个很宽泛，容易被曲解的词进行严格的划分。</p>  <h2>异常机制</h2>  <p>所谓异常机制也就是指的语言平台支持异常这种错误处理模式的机制，比如c#里的Exception对象，try{}catch{}finally{}结构，throw抛出异常的语句，等等，均为c#语言里对异常机制的实现。</p>  <p>异常机制是随着语言而存在的，<font color="#ff0000">一种语言既然支持异常机制，那么异常就是不可回避的，哪怕你自己不throw异常，你所使用的系统类，也会抛出异常给你，所以说讨论在系统里用不用异常是非常<strong>可笑</strong>的事情</font>。异常机制就像系统的后门，当一个过程执行中系统出错的时候，或者你认为系统不正常的时候，就把当时的情况拍个快照生成异常对象，通过特殊的通道通知调用这个过程的方法。</p>  <h2>异常对象</h2>  <p>异常对象是异常机制中用来描述异常，记录错误信息，可以说是错误发生是的快照，就跟你开快车闯红灯被天眼拍到的照片差不多。</p>  <h2>抛出异常</h2>  <p>所谓抛出异常就是异常机制中通知调用的方法本方法出错了的手段。而抛出异常也是很多人诟病异常对性能影响的地方，因为系统性能的开销都是由抛出异常所引起的。<strong><font color="#ff0000">但是抛出异常也无法避免，因为这是系统本身的特点，你不抛出异常，系统自己也会抛出，一旦系统抛出了异常对象，你怎么来避免这个性能的开销？</font></strong>没辙</p>  <p>比如方法A调用了方法B，方法B访问数据库，出错了，那么B就会抛出异常，而A就需要catch这个异常来处理。</p>  <p>抛出异常有两种形式，一种是系统抛出的异常，一种是我们自己认为在处理一段逻辑的时候当逻辑错误，就可以通过抛出一个异常对象，来通知调用这个方法的方法，这里出错了。</p>  <h3>系统抛出异常</h3>  <p>系统抛出的异常对编程人员来说是透明的，也就是我们不需要关心系统是如何得知出错了的，系统类库一旦出错就会将异常对象抛给我们调用它的方法，因为系统本身并不知道要如何处理这个错误。</p>  <h3>用户抛出异常</h3>  <p>用户抛出异常通常在自己写类库，定义一套API给别人使用的时候用到，这个时候我们并不知道要如何处理这些逻辑错误，所以就需要交给知道如何处理逻辑错误的方法去处理。</p>  <p>在C#里通过定义了throw关键字来抛出异常对象，这里除了抛出新创建的异常对象，也可以通过将已经catch到的异常重新抛出。如果不知道如何处理这个异常，重新抛出异常是很好的习惯，<font color="#ff0000">因为既然已经抛出了异常，那么性能已经损失了</font>，所以也不在乎多这么一丁点来更好的挽回错误的结果。</p>  <h2>处理异常</h2>  <p>所有的异常必须得到妥善的处理，也就是说你必须处理所有的异常。因为系统出错就抛异常，所以这个是c#骨子里的东西，无法避免，所以，系统里到处都会充斥着try{}catch{}。</p>  <p>但是try{}catch{}本身并不会影响系统的性能，所以在没有异常发生的时候try{}catch{}是不会让你系统变慢的，而一旦发生系统异常，你不处理系统就崩溃掉了，你到底是愿意系统慢一点点然后处理掉这个错误呢还是愿意系统崩溃掉呢？</p>  <p>对于处理异常这一点其实我觉得java那种比较严格的，要求严格声明并处理所有异常的方式比较好，能够强制让你重视起异常这回事来，免得系统崩溃掉才想起自己没处理这个异常。</p>  <p>&#160;</p>  <h1>如何处理</h1>  <p>如何正确的处理异常？这是个很多c#程序员都没最终搞明白的话题，很多人所了解的也无非就是不要用异常处理当业务逻辑，但是何谓用异常来处理逻辑就不得而知了。这里我来详细说明一下，什么地方要用异常，什么地方不要用。</p>  <p>首先有一个前提，异常机制是一个由底向上的冒泡的过程，所以正常的逻辑是，异常由底层抛出，由高层来处理。</p>  <h3>处理异常正确的例子</h3>  <p>要编写健壮的引用程序，首先要保证必须处理所有的系统异常，也就是调用.NET类库的方法的时候，这个方法可能抛出的异常</p>  <p>例：</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_2.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="113" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb.png" width="464" border="0" /></a> </p>  <p>我们可以看到，GetResponse方法会抛出两个异常 InvalidOperationException和WebException。那么我们就需要将调用的代码所在的catch单独处理这两个异常</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_4.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="210" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb_1.png" width="365" border="0" /></a> </p>  <p>如果你在这个方法中不知道应该如何处理这个异常，比如这个方法不上不下，和表现层离了好几层，而又需要在表现层通知用户或者由上层业务来决定是通知用户还是悄悄的进村，又或者是悄悄的重新尝试一次，那么自己不能决定的事情就要抛给上层去处理。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_6.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="69" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb_2.png" width="328" border="0" /></a> </p>  <p>有人可能会说.NET可以统一处理异常的，不过我不推荐那种大而全的处理方式，不够细致，很多时候会被奇怪的错误搞得你很追查错误的本源。且比如说遇到网络问题重试就没法处理。</p>  <p>异常必须就近处理，这样才能方便追查，而且注意那个“xxx方法出错了”那个地方，很重要，这个描述可以让你在系统排错的时候少走很多弯路，尽量写详细点。</p>  <p>如果你的代码是给别的程序员使用，而不是和最终用户直接交互，那么除了处理所有系统抛出的异常以外，还需要用异常来验证过滤入口参数。比如，假设你要给其他程序员提供一个将用户对象插入数据库的方法：</p>  <p>   <div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:f8cf4fe8-3ce5-475e-9b52-f0192a0eabd4" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #000000;">    </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> InsertUser(User user)
    {
        </span><span style="color: #0000FF;">if</span><span style="color: #000000;">(user</span><span style="color: #000000;">==</span><span style="color: #0000FF;">null</span><span style="color: #000000;">)
        {
            </span><span style="color: #0000FF;">throw</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> ArgumentNullException(</span><span style="color: #800000;">"</span><span style="color: #800000;">参数user为null</span><span style="color: #800000;">"</span><span style="color: #000000;">);
        }
        </span><span style="color: #008000;">//</span><span style="color: #008000;">调用Orm</span><span style="color: #008000;">
</span><span style="color: #000000;">    }</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
</p>

<p>这里我们验证了入口参数，并尽早的抛出了异常，因为这里抛出的异常和不处理等db操作抛出异常，肯定是这里手动抛出的开销更小。这里有一个原则就是，如果这个参数会造成底层代码直接出错，那么就就近处理它，而不要放任其在底层造成系统异常的抛出。当然还有一个原则就是不要在这里判断业务逻辑，比如上面的例子就不要在这里验证User的属性的数值是不是合法之类的。</p>

<p>&#160;</p>

<h3>处理异常错误的例子</h3>

<p><strong>1：用异常验证用户输入</strong></p>

<p>用户输入的合法性验证是属于业务逻辑的一部分，绝对不要用异常去处理，注意，是用户输入，所以这个经验仅限于表现层逻辑</p>

<p><strong><font color="#ff0000">典型的错误1：</font></strong></p>

<div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:c2406ac7-4dac-47dd-8e38-937fba6dc3de" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #0000FF;">try</span><span style="color: #000000;">
{
    </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> i</span><span style="color: #000000;">=</span><span style="color: #0000FF;">int</span><span style="color: #000000;">.Parse(textBox1.Text);
}
</span><span style="color: #0000FF;">catch</span><span style="color: #000000;">(Exception ex)
{
    alert(“不要输入非数字”);
}
</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p><strong><font color="#ff0000">典型错误2：</font></strong></p>

<div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:7e146117-bc2f-47ef-ad85-198ffe2ea6ec" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #0000FF;">void</span><span style="color: #000000;"> ValidateInput(</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> i)
{
    </span><span style="color: #0000FF;">if</span><span style="color: #000000;">(i</span><span style="color: #000000;">&lt;</span><span style="color: #800080;">0</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">i</span><span style="color: #000000;">&gt;</span><span style="color: #800080;">100</span><span style="color: #000000;">)
    {
        </span><span style="color: #0000FF;">throw</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Exception(</span><span style="color: #800000;">"</span><span style="color: #800000;">输入数据范围错误</span><span style="color: #800000;">"</span><span style="color: #000000;">);
    }
}
</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p>&#160;</p>

<p>以上两种错误都是错误使用异常的典型，</p>

<p><strong>2：将异常延迟到底层</strong></p>

<p>这一点我们在正确的例子里提到过</p>

<p><strong><font color="#ff0000">典型错误3：</font></strong></p>

<div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:10ec8e9b-869c-432f-808e-93625af1b522" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #000000;">        </span><span style="color: #0000FF;">try</span><span style="color: #000000;">
        {
            </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> name</span><span style="color: #000000;">=</span><span style="color: #000000;">Request.QueryString[</span><span style="color: #800000;">"</span><span style="color: #800000;">xx</span><span style="color: #800000;">"</span><span style="color: #000000;">];
            List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">User</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> userls</span><span style="color: #000000;">=</span><span style="color: #000000;">User.QueryUserByName(name);
        }
        </span><span style="color: #0000FF;">catch</span><span style="color: #000000;">(SqlException ex)
        {
        }</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p>这个错误在于完全不验证用户输入而直接把数据的验证抛向数据库，等待数据库报错来判断用户输入的正确性，这个是非常致命的错误，很多注入漏洞都是由此产生的。</p>

<p><strong>3：完全不用异常机制</strong></p>

<p>产生这个错误肯定是一个非常脑残的决定造成的。不过很多时候某些不了解异常机制的人，由于对异常的性能开销的恐惧感，经常会做出这么脑残的决定。</p>

<p><font color="#ff0000"><strong>典型错误4：</strong></font></p>

<p>
  <div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:76da1f12-5924-46c9-b769-971712029758" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #000000;">    </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">bool</span><span style="color: #000000;"> InsertUser(User user,</span><span style="color: #0000FF;">ref</span><span style="color: #000000;"> </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> errcode)
    {
        </span><span style="color: #0000FF;">if</span><span style="color: #000000;">(user</span><span style="color: #000000;">==</span><span style="color: #0000FF;">null</span><span style="color: #000000;">)
        {
            errcode</span><span style="color: #000000;">=</span><span style="color: #800080;">110</span><span style="color: #000000;">;</span><span style="color: #008000;">//</span><span style="color: #008000;">参数为空错误的代码</span><span style="color: #008000;">
</span><span style="color: #000000;">            </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> </span><span style="color: #0000FF;">false</span><span style="color: #000000;">;
        }
        </span><span style="color: #008000;">//</span><span style="color: #008000;">调用Orm</span><span style="color: #008000;">
</span><span style="color: #000000;">    }</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
</p>

<p>感觉就是一夜回到了解放前，性能倒是高了，但是系统异常怎么办呢？一旦数据库出错就只等着系统崩溃了。某些有经验的说我会把下面的try{}catch{}起来，不过那不是脱了裤子放屁么，异常都抛出来了，开销已经产生了，结果换来的是牺牲了异常对象的丰富信息而换来了畸形的系统逻辑。性能也没得到提高。</p>

<h1>异常对性能的影响</h1>

<p>异常机制是C#的特征，因此决定了你不可能逃避，所以讨论异常给你带来了多大开销都是扯淡，没有必要的研究，从根本上无法解决问题。我们应该弄清楚的是，异常的抛出给系统带来什么样的影响，如何在保证系统健壮性的基础上减小不必要的性能消耗。</p>

<p>1.异常的性能开销随着调用栈的深度增加而增大。</p>

<p>对比测试：</p>

<p>测试代码1</p>

<div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:d05de336-351b-413a-af12-2e9d23c18134" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #000000;">            Stopwatch sw </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Stopwatch();
            sw.Start();
            </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> i </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">; i </span><span style="color: #000000;">&lt;</span><span style="color: #000000;"> </span><span style="color: #800080;">10</span><span style="color: #000000;">; i</span><span style="color: #000000;">++</span><span style="color: #000000;">)
            {
                </span><span style="color: #0000FF;">try</span><span style="color: #000000;">
                {
                    </span><span style="color: #0000FF;">throw</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Exception(</span><span style="color: #800000;">"</span><span style="color: #800000;">test</span><span style="color: #800000;">"</span><span style="color: #000000;">);
                }
                </span><span style="color: #0000FF;">catch</span><span style="color: #000000;"> { }
            }
            sw.Stop();
            MessageBox.Show(sw.ElapsedMilliseconds </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">ms</span><span style="color: #800000;">"</span><span style="color: #000000;">);</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p>测试结果：</p>

<table cellspacing="0" cellpadding="2" width="400" border="1"><tbody>
    <tr>
      <td valign="top" width="80">调用次数</td>

      <td valign="top" width="80">第一次</td>

      <td valign="top" width="80">第二次</td>

      <td valign="top" width="80">第三次</td>

      <td valign="top" width="80">第四次</td>
    </tr>

    <tr>
      <td valign="top" width="80">时间</td>

      <td valign="top" width="80"><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_8.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="103" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb_3.png" width="105" border="0" /></a> </td>

      <td valign="top" width="80"><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_10.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="107" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb_4.png" width="108" border="0" /></a> </td>

      <td valign="top" width="80"><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_12.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="107" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb_5.png" width="109" border="0" /></a> </td>

      <td valign="top" width="80"><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_14.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="106" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb_6.png" width="108" border="0" /></a> </td>
    </tr>
  </tbody></table>

<p>&#160;</p>

<p>测试代码2</p>

<div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:60fe64b8-4eb6-438e-9bbe-d73458916ad7" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #000000;">           Stopwatch sw </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Stopwatch();
            sw.Start();
            </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> i </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">; i </span><span style="color: #000000;">&lt;</span><span style="color: #000000;"> </span><span style="color: #800080;">10</span><span style="color: #000000;">; i</span><span style="color: #000000;">++</span><span style="color: #000000;">)
            {
                </span><span style="color: #0000FF;">try</span><span style="color: #000000;">
                {
                    System.IO.File.OpenRead(</span><span style="color: #800000;">"</span><span style="color: #800000;">c:\\不存在的txt.txt</span><span style="color: #800000;">"</span><span style="color: #000000;">);
                }
                </span><span style="color: #0000FF;">catch</span><span style="color: #000000;"> { }
            }
            sw.Stop();
            MessageBox.Show(sw.ElapsedMilliseconds </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">ms</span><span style="color: #800000;">"</span><span style="color: #000000;">);</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p>&#160;</p>

<p>测试结果</p>

<table cellspacing="0" cellpadding="2" width="402" border="1"><tbody>
    <tr>
      <td valign="top" width="80">调用次数</td>

      <td valign="top" width="80">第一次</td>

      <td valign="top" width="80">第二次</td>

      <td valign="top" width="80">第三次</td>

      <td valign="top" width="80">第四次</td>
    </tr>

    <tr>
      <td valign="top" width="80">时间</td>

      <td valign="top" width="80"><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_16.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="109" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb_7.png" width="110" border="0" /></a> </td>

      <td valign="top" width="80"><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_18.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="106" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb_8.png" width="108" border="0" /></a> </td>

      <td valign="top" width="80"><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_20.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="108" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb_9.png" width="109" border="0" /></a> </td>

      <td valign="top" width="80"><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_22.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="107" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb_10.png" width="109" border="0" /></a> </td>
    </tr>
  </tbody></table>

<p>小结：由此我们可以发现随着调用栈的深入，性能开销也越大，所以异常应该尽早抛出。</p>

<p>2.对输入的数据应该在业务逻辑中严格检查。</p>

<p>3.<strong><font color="#ff0000">try{}catch{}不会造成任何的系统开销，造成系统开销的是throw 抛出异常</font></strong>，这是再三强调的了</p>

<p>诸如：</p>

<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_24.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="37" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/806c1358f949_8FD2/image_thumb_11.png" width="500" border="0" /></a> </p>

<p>这种言论就纯属脑残了。</p>

<p>&#160;</p>

<p>&#160;</p>

<h1>结论</h1>

<p>&#160;</p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p></p>

<p><font face="仿宋_GB2312" color="#ff0000" size="4"><strong>异常机制是C#内置的错误处理机制，你无法避免它，唯一正确的道路是学会如何正确使用</strong></font></p>

<p><strong><font face="仿宋_GB2312" color="#ff0000" size="4"></font></strong></p>

<p><strong><font face="仿宋_GB2312" color="#ff0000" size="4">希望大家正确使用异常，好好学习天天向上</font></strong></p><img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1627105.html?type=1" width="1" height="1" alt=""/><p>评论: 34　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/12/18/1627105.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/12/18/1627105.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56855/" target="_blank">NDepend 3.0已与Visual Studio集成</a><span style="color:gray">(2010-02-10 16:17)</span><br/>· <a href="http://news.cnblogs.com/n/56854/" target="_blank">Ruby in Steel 1.5发布，去除IronRuby支持</a><span style="color:gray">(2010-02-10 16:14)</span><br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>利用电信能力开放平台轻松开发短信应用</title><link>http://www.cnblogs.com/Alexander-Lee/archive/2009/12/04/1617317.html</link><dc:creator>亚历山大同志</dc:creator><author>亚历山大同志</author><pubDate>Fri, 04 Dec 2009 14:39:00 GMT</pubDate><guid>http://www.cnblogs.com/Alexander-Lee/archive/2009/12/04/1617317.html</guid><description><![CDATA[<p>阅读: 3253 评论: 31 作者: <a href="http://www.cnblogs.com/Alexander-Lee/" target="_blank">亚历山大同志</a> 发表于 2009-12-04 22:39 <a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/12/04/1617317.html" target="_blank">原文链接</a></p><p>中国电信在最近开放了其能力平台，现在这个项目正处于beta1的状态，利用能力平台，开发者可以轻松的通过统一的API调用电信提供的多种能力，包括语音呼叫（多方通话）、短信、IVR、GPSOne定位等多种能力，并且将这些能力整合成自己的特色应用，通过电信的MM平台向所有中国电信的3G用户推广，销售，并从中获取收益。相对于iphone和android的平台，电信的能力开放平台更加接近运营商的核心业务，合理利用可以创造更加独特的应用。</p>  <p>本文用一个短信应用作为例子来看看这一切是多么的简单。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/630de582b376_13E47/image_2.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/630de582b376_13E47/image_thumb.png" width="346" height="162" /></a> </p>  <p>第一步：用户注册成为能力开放平台AP；    <br />第二步：用户登录能力开放平台；     <br />第三步：购买短信能力接口；（<strong>beta期间免费哟</strong>）     <br />第四步：调用能力开放平台认证鉴权接口，获得认证码；     <br />第五步：获得认证码以后，调用短信发送接口。</p>  <h1> 接口描述</h1>  <p><b>认证鉴权接口</b><b> </b><b>：</b></p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/630de582b376_13E47/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/630de582b376_13E47/image_thumb_1.png" width="535" height="254" /></a> </p>  <p><b>AuthRequestValue </b><b>格式如下：</b></p>  <p>TimeStamp + “$” + APID+ “$” + APUserAccount + “$” + FunID + “$” + Authenticator</p>  <p>其中Authenticator的生成算法如下：</p>  <p>Authenticator = Base64(SHA1 (TimeStamp + “$” + APID+ “$” + APUserAccount + “$” + FunID + “$” + APKEY))</p>  <p>其中， APKEY是能力开放平台颁发给该AP的密钥。</p>  <p><b>应答消息</b></p>  <p></p>  <p></p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/630de582b376_13E47/image_6.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/630de582b376_13E47/image_thumb_2.png" width="413" height="157" /></a> </p>  <p><b>AuthResponseValue</b><b>格式如下：</b></p>  <p>Result + “$”+ TransactionID + “$”+ Token+ “$” + ErrorDescription+ “$” + TimeStamp</p>  <p><b>短信发送接口：</b></p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/630de582b376_13E47/image_8.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/630de582b376_13E47/image_thumb_3.png" width="507" height="237" /></a> </p>  <p><b>其中</b><b>SendMsgRequestValue</b><b>格式如下：</b></p>  <p>Token+ “$” + Phone + “$” + Msg + “$” + From</p>  <p><b>应答消息</b></p> <a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/630de582b376_13E47/image_10.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/630de582b376_13E47/image_thumb_4.png" width="427" height="76" /></a>   <p></p>  <p><b>SendMsgResponseValue</b><b>格式：</b></p>  <p>Result</p>  <h1><a name="#"><strong>应用接入</strong></a></h1>  <p>接入流程简述</p>  <p>一个应用接入到能力开放平台，意味着以下两个方面：   <br />(1)、该应用遵循能力开放平台APP接入规范，可以从能力开放平获取用户的ApKey    <br />(2)、该应用符合能力开放平台API接入规范，可以调用能力开放平提供的丰富的API接口</p>  <p>一个应用要接入到能力开放平台，需要经过以下三个步骤：   <br />(1).通过能力开放平台申请AP账号    <br />(2).调用认证鉴权接口获得认证码    <br />(3).使用获得的认证码来调用API</p>  <p>&#160;</p>  <h1>开发实例</h1>  <p>&#160;</p>  <h2>C#的例子</h2>  <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:12f4c7d6-907f-4d8b-aeac-4861bcb79475" class="wlWriterEditableSmartContent"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> SendMsg()
    {
        </span><span style="color: #008000;">//</span><span style="color: #008000;">1.调用能力管控认证鉴权接口，获取Token</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> authResult </span><span style="color: #000000;">=</span><span style="color: #000000;"> AMCPForAP.Auth(AuthInterfaceURL, APID, FuncID, APUserID, APKey);
        </span><span style="color: #0000FF;">string</span><span style="color: #000000;">[] authResults </span><span style="color: #000000;">=</span><span style="color: #000000;"> authResult.Split(’$’);

        </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> result </span><span style="color: #000000;">=</span><span style="color: #000000;"> Int32.Parse(authResults[</span><span style="color: #800080;">0</span><span style="color: #000000;">]);

        </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (result </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">)
        {
            </span><span style="color: #008000;">//</span><span style="color: #008000;">验证码</span><span style="color: #008000;">
</span><span style="color: #000000;">            </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> token </span><span style="color: #000000;">=</span><span style="color: #000000;"> authResults[</span><span style="color: #800080;">2</span><span style="color: #000000;">];
            </span><span style="color: #008000;">//</span><span style="color: #008000;">接收号码</span><span style="color: #008000;">
</span><span style="color: #000000;">            </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> num1 </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">13888888888</span><span style="color: #800000;">"</span><span style="color: #000000;">;
            </span><span style="color: #008000;">//</span><span style="color: #008000;">消息内容</span><span style="color: #008000;">
</span><span style="color: #000000;">            </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> msg </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">hello</span><span style="color: #800000;">"</span><span style="color: #000000;">;
            </span><span style="color: #008000;">//</span><span style="color: #008000;">发送电话号码</span><span style="color: #008000;">
</span><span style="color: #000000;">            </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> from </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">""</span><span style="color: #000000;">;

            </span><span style="color: #008000;">//</span><span style="color: #008000;">发送消息</span><span style="color: #008000;">
</span><span style="color: #000000;">            </span><span style="color: #0000FF;">this</span><span style="color: #000000;">.Send(token, num1, msg, from);
        }
        </span><span style="color: #008000;">//</span><span style="color: #008000;">2.如果用户不存在，调用注册接口注册</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #0000FF;">else</span><span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (result </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #000000;">-</span><span style="color: #800080;">10020</span><span style="color: #000000;">)
        {

            </span><span style="color: #0000FF;">string</span><span style="color: #000000;">[] registerResults </span><span style="color: #000000;">=</span><span style="color: #000000;"> AMCPForAP.APUserRegister(Int32.Parse(APID), APUserID, </span><span style="color: #800000;">"</span><span style="color: #800000;">02888888888</span><span style="color: #800000;">"</span><span style="color: #000000;">, APKey, </span><span style="color: #800000;">"</span><span style="color: #800000;">http://localhost/InterfaceForAP/InterfaceForAP.asmx</span><span style="color: #800000;">"</span><span style="color: #000000;">).Split(’$’);
            </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> registerResult </span><span style="color: #000000;">=</span><span style="color: #000000;"> Int32.Parse(registerResults[</span><span style="color: #800080;">0</span><span style="color: #000000;">]);
            </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (registerResult </span><span style="color: #000000;">!=</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">)
            {
                </span><span style="color: #0000FF;">return</span><span style="color: #000000;">;
            }

            </span><span style="color: #008000;">//</span><span style="color: #008000;">3.再次调用能力管控认证鉴权接口，获取Token</span><span style="color: #008000;">
</span><span style="color: #000000;">            authResult </span><span style="color: #000000;">=</span><span style="color: #000000;"> AMCPForAP.Auth(AuthInterfaceURL, APID, FuncID, APUserID, APKey);
            authResults </span><span style="color: #000000;">=</span><span style="color: #000000;"> authResult.Split(’$’);

            result </span><span style="color: #000000;">=</span><span style="color: #000000;"> Int32.Parse(authResults[</span><span style="color: #800080;">0</span><span style="color: #000000;">]);

            </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (result </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">)
            {
                </span><span style="color: #008000;">//</span><span style="color: #008000;">验证码</span><span style="color: #008000;">
</span><span style="color: #000000;">                </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> token </span><span style="color: #000000;">=</span><span style="color: #000000;"> authResults[</span><span style="color: #800080;">2</span><span style="color: #000000;">];
                </span><span style="color: #008000;">//</span><span style="color: #008000;">接收号码</span><span style="color: #008000;">
</span><span style="color: #000000;">                </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> num1 </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">this</span><span style="color: #000000;">.txtPhoneNumber.Text.Trim();
                </span><span style="color: #008000;">//</span><span style="color: #008000;">消息内容</span><span style="color: #008000;">
</span><span style="color: #000000;">                </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> msg </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">this</span><span style="color: #000000;">.txtMsg.Text.Trim();
                </span><span style="color: #008000;">//</span><span style="color: #008000;">发送电话号码</span><span style="color: #008000;">
</span><span style="color: #000000;">                </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> from </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">""</span><span style="color: #000000;">;

                </span><span style="color: #008000;">//</span><span style="color: #008000;">发送消息</span><span style="color: #008000;">
</span><span style="color: #000000;">                </span><span style="color: #0000FF;">this</span><span style="color: #000000;">.Send(token, num1, msg, from);
            }
            </span><span style="color: #0000FF;">else</span><span style="color: #000000;">
            {
                </span><span style="color: #0000FF;">return</span><span style="color: #000000;">;
            }

        }
        </span><span style="color: #0000FF;">else</span><span style="color: #000000;">
        {
            </span><span style="color: #0000FF;">return</span><span style="color: #000000;">;
        }
    }

    </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> Send(</span><span style="color: #0000FF;">string</span><span style="color: #000000;"> token, </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> num1, </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> msg, </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> from)
    {
        </span><span style="color: #008000;">//</span><span style="color: #008000;">生成请求字符串</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> sendMsgRequest </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">http://118.123.249.4/ims/ghsendim.php?SendMsgRequest=</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> token </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">$</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> num1 </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">$</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> PSOCryptography.ConvertStringToBase64String(msg) </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">$</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> from;

        </span><span style="color: #0000FF;">this</span><span style="color: #000000;">.TextBox1.Text </span><span style="color: #000000;">=</span><span style="color: #000000;"> sendMsgRequest;

        </span><span style="color: #008000;">//</span><span style="color: #008000;">发送短信</span><span style="color: #008000;">
</span><span style="color: #000000;">        </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> sendResult </span><span style="color: #000000;">=</span><span style="color: #000000;"> AMCPForAP.GetPageFromURL(sendMsgRequest);

        
        </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (</span><span style="color: #000000;">!</span><span style="color: #000000;">sendResult.IndexOf(</span><span style="color: #800000;">"</span><span style="color: #800000;">200</span><span style="color: #800000;">"</span><span style="color: #000000;">) </span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">)
        {
            </span><span style="color: #008000;">//</span><span style="color: #008000;">发送失败</span><span style="color: #008000;">
</span><span style="color: #000000;">            </span><span style="color: #0000FF;">return</span><span style="color: #000000;">;
        }
        
    }</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p>&#160;</p>

<h1>常见问题</h1>

<p>1.什么是AP?
  <br />答：应用服务提供商。

  <br />2.什么是Token?

  <br />由能力控制平台生成的，AP调用能力时必须出示的凭证。

  <br />3.注册成为能力开放平台用户有什么资质要求吗？

  <br />答：只要您有固定的手机号和提供个人身份证号码即可。

  <br />4.正式环境介绍

  <br />答：在正式环境中，开发者操作的都是真实的数据。所进行的操作会对真实的交易数据产生影响，应用在线上测试以及上线运行中状态才可以访问正式环境，其调用次数会受到限制。</p>

<p>&#160;</p>

<h1>利好消息</h1>

<p>如果你正在使用天翼的手机，如果你想要开发电信的3G业务，赶紧加入吧，</p>

<p>能力开放平台的地址：<a title="http://www.ctopen.cn/" href="http://www.ctopen.cn/">http://www.ctopen.cn/</a> 赶紧注册，beta期间多数能力是免费的。</p>

<p>如果你有兴趣写关于能力开放平台的Blog，请跟我联系，有机会获得<strong>免费长话</strong>的大礼包哟</p><img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1617317.html?type=1" width="1" height="1" alt=""/><p>评论: 31　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/12/04/1617317.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/12/04/1617317.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56855/" target="_blank">NDepend 3.0已与Visual Studio集成</a><span style="color:gray">(2010-02-10 16:17)</span><br/>· <a href="http://news.cnblogs.com/n/56854/" target="_blank">Ruby in Steel 1.5发布，去除IronRuby支持</a><span style="color:gray">(2010-02-10 16:14)</span><br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>再来谈谈切换输入法以及IMM/IME</title><link>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/26/1611266.html</link><dc:creator>亚历山大同志</dc:creator><author>亚历山大同志</author><pubDate>Thu, 26 Nov 2009 05:23:00 GMT</pubDate><guid>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/26/1611266.html</guid><description><![CDATA[<p>阅读: 1380 评论: 0 作者: <a href="http://www.cnblogs.com/Alexander-Lee/" target="_blank">亚历山大同志</a> 发表于 2009-11-26 13:23 <a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/26/1611266.html" target="_blank">原文链接</a></p><p>本文旨在对前文的遗漏之处做一个patch，继而详细和大家讨论一下输入法相关的内容，毕竟给中国人用的程序难免会遇到打字的需求，提到打字必然会遇到输入法。</p>  <p>&#160;</p>  <p>首先是对前文的一个补遗，如果你直接copy前文的代码执行可能会发现本没有出现想象中的鼠标一点，输入法就变了，为啥呢。因为我漏掉了一个步骤，也就是对输入法状态的重置。</p>  <p>需要在调用ImmSetConvertionStatus前对要切换输入法的控件设置 ImeMode=ImeMode.On。</p>  <p>那么这个ImeMode究竟起到什么作用呢，众所周知，在winform的TextBox等控件（包括MaskedTextBox）都包含了一个ImeMode的属性，这个属性其实就是在底层调用了ImmSetConvertionStatus方法来设置输入法为指定的几个枚举值：</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/IMMIME_9733/image_2.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="142" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/IMMIME_9733/image_thumb.png" width="599" border="0" /></a></p>  <p>图1 </p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/IMMIME_9733/image_4.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="264" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/IMMIME_9733/image_thumb_1.png" width="134" border="0" /></a></p>  <p>图2 </p>  <p>根据Reflector的结果发现其中对这个枚举进行了细化</p>  <p>   <div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:50ade017-c6ea-45b5-b988-d5cea7aaefdf" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #000000;">    </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> ImeModeConversion()
    {
        japaneseTable </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> ImeMode[] { ImeMode.Inherit, ImeMode.Disable, ImeMode.Off, ImeMode.Off, ImeMode.Hiragana, ImeMode.Hiragana, ImeMode.Katakana, ImeMode.KatakanaHalf, ImeMode.AlphaFull, ImeMode.Alpha };
        koreanTable </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> ImeMode[] { ImeMode.Inherit, ImeMode.Disable, ImeMode.Alpha, ImeMode.Alpha, ImeMode.HangulFull, ImeMode.Hangul, ImeMode.HangulFull, ImeMode.Hangul, ImeMode.AlphaFull, ImeMode.Alpha };
        chineseTable </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> ImeMode[] { ImeMode.Inherit, ImeMode.Disable, ImeMode.Off, ImeMode.Close, ImeMode.On, ImeMode.OnHalf, ImeMode.On, ImeMode.OnHalf, ImeMode.Off, ImeMode.Off };
        unsupportedTable </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> ImeMode[</span><span style="color: #800080;">0</span><span style="color: #000000;">];
    }
</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
</p>

<p>由此，如果我们只需要设置输入法的全角半角，或者日文输入法的平假名片假名切换就只需要调用 TextBox或者类似控件的ImeMode属性就行了。不过根据Reflector得到的代码我发现其实设置ImeMode来调用ImmSetConvertionStatus的时候Sentence的值恒为0，那么也就是说如果是要切换的日语或者中文的组句特性的话就不能使用ImeMode属性而是用前文的调用win32api的方式来实现。</p>

<p>根据之前的讨论我们可以发现IMM和IME的关系，IMM也就是操作系统的文字服务，只有东亚版本的windows才有，而IME就是输入法的实现程序，包括微软拼音，智能ABC，五笔之类的都是IME的程序，IME注册到IMM中，由IMM来决定当前使用的IME程序，而用户不能直接和IME打交道，而只能通过IMM提供的api接口，比如我们之前用到的ImmSetConvertionStatus。典型的代理模式应用</p>

<p>当然IMM提供的API函数还是IME程序和IMM交互的接口，如果我们要实现自己的输入法的话就只用通过这些接口就行了。</p>

<p>附一：</p>

<p>Mode 和Setence值的含义，按位定义</p>

<p>|&#160;&#160;&#160;&#160; 1/0&#160;&#160;&#160; |&#160;&#160; 1/0&#160;&#160;&#160; |&#160;&#160;&#160;&#160; 1/0&#160;&#160;&#160; |&#160; 1/0&#160;&#160; |&#160; 1/0&#160;&#160; |&#160;&#160; 1/0&#160;&#160;&#160; |&#160; 1/0 |&#160; 1/0&#160;&#160; |&#160; 1/0 |&#160;&#160; 1/0&#160; |&#160;&#160; 1/0&#160;&#160;&#160; |&#160; 1/0 |
  <br />|_98(me)保留_|_中文标点_|_自定义字符_|_不转换_|_软键盘_|_韩(汉字)_|_内码_|_日罗马_|_全角_|_片假名_|_本地语言_|</p>

<p>|&#160;&#160;&#160; 1/0&#160;&#160; |&#160;&#160; 1/0&#160;&#160;&#160; |&#160;&#160; 1/0&#160;&#160;&#160; |&#160;&#160; 1/0&#160;&#160;&#160; |&#160;&#160; 1/0&#160;&#160;&#160; |&#160;&#160; 1/0&#160;&#160;&#160; |
  <br />|_逐键提示_|_词语联想_|_自动模式_|_单字模式_|_多个子句_|_没有组句_|</p>

<p>我在上一篇中的表中， 片假名半角的mode值是19，换成2进制就是10011，查表得到的就是</p>

<p>内码|半角|片假名|本地语言</p>

<p>正好符合。</p><img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1611266.html?type=1" width="1" height="1" alt=""/><p>评论: 0　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/26/1611266.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/26/1611266.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56855/" target="_blank">NDepend 3.0已与Visual Studio集成</a><span style="color:gray">(2010-02-10 16:17)</span><br/>· <a href="http://news.cnblogs.com/n/56854/" target="_blank">Ruby in Steel 1.5发布，去除IronRuby支持</a><span style="color:gray">(2010-02-10 16:14)</span><br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>在应用程序中精确切换输入法</title><link>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/23/1608633.html</link><dc:creator>亚历山大同志</dc:creator><author>亚历山大同志</author><pubDate>Mon, 23 Nov 2009 04:14:00 GMT</pubDate><guid>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/23/1608633.html</guid><description><![CDATA[<p>阅读: 2030 评论: 9 作者: <a href="http://www.cnblogs.com/Alexander-Lee/" target="_blank">亚历山大同志</a> 发表于 2009-11-23 12:14 <a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/23/1608633.html" target="_blank">原文链接</a></p><p>如果在你的程序里需要输入很多的内容，比如各类单据，如果在进入每一个录入框的时候都能自动把输入法切换到合适的状态将会是一个很酷的特性，相比炫丽的界面而言打字到手抽筋的录入人员们对此会更加感兴趣。在winform中切换输入法是很简单的事情：</p>  <p>   </p><div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:25f5beb6-41fb-4b10-9933-cdb17a69b0fe" style="margin: 0px; padding: 0px; display: inline; float: none;"><pre style="overflow: auto; background-color: #ffffff; white-space: pre-wrap; word-wrap: break-word;"><span style="color: #000000;">            </span><span style="color: #0000ff;">foreach</span><span style="color: #000000;"> (InputLanguage iL </span><span style="color: #0000ff;">in</span><span style="color: #000000;"> InputLanguage.InstalledInputLanguages)<br />            {<br />                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (iL.LayoutName </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">智能ABC</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br />                {<br />                    InputLanguage.CurrentInputLanguage </span><span style="color: #000000;">=</span><span style="color: #000000;"> iL;<br />                    </span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />                }<br />            }</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>&nbsp;</p>

<p>这样子就能很轻松的吧输入法切换到智能ABC了。</p>

<p>但是这样子的效果是不完美的，这个方法不能指定IME的状态，也就是IME的转换状态。这个概念是只有远东地区的windows才存在的状态，因为对于英语国家来说输入根本不存在输入法，而法语，俄语等拉丁语系的拼音文字的语言都只需要简单的修改键映射关系就行了，只有受中文影响的东亚地区有输入法的概念，比如日文和朝鲜文，为了方便输入，这些IME中都有很多状态，比如微软日文输入法：</p>

<p><a target="_blank" href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/a527410bd2ed_9954/image_2.png"><img title="image" style="border: 0px none ; display: inline;" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/a527410bd2ed_9954/image_thumb.png" width="244" border="0" height="173" /></a> </p>

<p>日文输入包含了全角半角平假名，全角半角片假名等录入的状态，还包括了：</p>

<p><a target="_blank" href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/a527410bd2ed_9954/image_4.png"><img title="image" style="border: 0px none ; display: inline;" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/a527410bd2ed_9954/image_thumb_1.png" width="244" border="0" height="152" /></a> </p>

<p>普通，名字，对话和不转换四种假名到当用汉字的转换模式</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>汉语的输入法简单一些，不存在对汉字的转换，不过也存在为了中英交替录入（牛逼哄哄的日本人喜欢用片假名替换英文所以不存在交替录入）而存在的中英录入模式转换，中英标点符号装换，还有全角半角的转换：</p>

<p><a target="_blank" href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/a527410bd2ed_9954/image_6.png"><img title="image" style="border: 0px none ; display: inline;" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/a527410bd2ed_9954/image_thumb_2.png" width="196" border="0" height="78" /></a> </p>

<p>如果是用的很古老的智能ABC的话，那么还存在双打和标准模式的切换。</p>

<p>对于这些五花八门的输入法中的输入模式，如果在选择了确定要输入法，同时也要确定要唯一定位到输入的模式，那么 InputLanguage 类的功能就捉襟见肘了。</p>

<p>在windows的文字服务IMM中对IME提供了ConvertionStatus的接口来确定输入法的工作模式，在Win32API中就是</p>

<p>ImmGetConversionStatus和ImmSetConversionStatus</p>

<p>这两个函数都有三个参数，一个是输入法IME的句柄，一个是mode，一个是sentence，最重要的就是mode和sentence这两个参数了，他们就是确定输入法状态的数据。经过测试发现，每个输入法的值都不一样，所以看MSDN去解析这两个int变量所对应的枚举值有哪些意义完全没必要，太复杂了，而我们只需要精确的切换到某个模式，只需要记录下这些模式下mode和sentence的值就行了。</p>

<p>下面是中文输入法的状态和mode值的对应关系表</p>

<p>双打模式（包括单双混合，比如微软输入法）</p>

<table width="400" border="1" cellpadding="2" cellspacing="0"><tr>
      <td width="200" valign="top">输入法状态</td>

      <td width="200" valign="top">mode值</td>
    </tr>

    <tr>
      <td width="200" valign="top">中文输入-半角-中文符号</td>

      <td width="200" valign="top">-2147482623</td>
    </tr>

    <tr>
      <td width="200" valign="top">中文输入-全角-中文符号</td>

      <td width="200" valign="top">-2147482615</td>
    </tr>

    <tr>
      <td width="200" valign="top">中文输入-半角-英文符号</td>

      <td width="200" valign="top">-2147483647</td>
    </tr>

    <tr>
      <td width="200" valign="top">中文输入-全角-英文符号</td>

      <td width="200" valign="top">-2147483639</td>
    </tr>

    <tr>
      <td width="200" valign="top">英文输入-半角-中文符号</td>

      <td width="200" valign="top">-2147482624</td>
    </tr>

    <tr>
      <td width="200" valign="top">英文输入-全角-中文符号</td>

      <td width="200" valign="top">-2147482616</td>
    </tr>

    <tr>
      <td width="200" valign="top">英文输入-半角-英文符号</td>

      <td width="200" valign="top">-2147483648</td>
    </tr>

    <tr>
      <td width="200" valign="top">英文输入-全角-英文符号</td>

      <td width="200" valign="top">-2147483640</td>
    </tr>
  </table>

<p>&nbsp;</p>

<p>标准模式（全拼模式，比如智能ABC的标准模式）</p>

<table width="400" border="1" cellpadding="2" cellspacing="0"><tr>
      <td width="200" valign="top">输入法状态</td>

      <td width="200" valign="top">mode值</td>
    </tr>

    <tr>
      <td width="200" valign="top">中文输入-半角-中文符号</td>

      <td width="200" valign="top">1025</td>
    </tr>

    <tr>
      <td width="200" valign="top">中文输入-全角-中文符号</td>

      <td width="200" valign="top">1033</td>
    </tr>

    <tr>
      <td width="200" valign="top">中文输入-半角-英文符号</td>

      <td width="200" valign="top">1</td>
    </tr>

    <tr>
      <td width="200" valign="top">中文输入-全角-英文符号</td>

      <td width="200" valign="top">9</td>
    </tr>

    <tr>
      <td width="200" valign="top">英文输入-半角-中文符号</td>

      <td width="200" valign="top">1024</td>
    </tr>

    <tr>
      <td width="200" valign="top">英文输入-全角-中文符号</td>

      <td width="200" valign="top">1032</td>
    </tr>

    <tr>
      <td width="200" valign="top">英文输入-半角-英文符号</td>

      <td width="200" valign="top">0</td>
    </tr>

    <tr>
      <td width="200" valign="top">英文输入-全角-英文符号</td>

      <td width="200" valign="top">8</td>
    </tr>
  </table>

<p>&nbsp;</p>

<p>由于不同的输入法对于模式的支持不同，比如搜狗支持的是标准模式，但是由于本身的功能又可以双打，但是设置模式却要用标准模式的值，而微软拼音是双打模式，而和同在双打模式智能ABC的sentence值又不一样，所以还是要根据具体的输入法测试后决定用什么数值来实现转换。</p>

<p>附1：</p>

<p>转换的代码：</p>

<p>首先注册Win32API的方法</p>

<div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:f11acb7f-74c7-4c98-a8a8-47eba28d1731" style="margin: 0px; padding: 0px; display: inline; float: none;"><pre style="overflow: auto; background-color: #ffffff; white-space: pre-wrap; word-wrap: break-word;"><span style="color: #000000;">        [DllImport(</span><span style="color: #800000;">"</span><span style="color: #800000;">imm32.dll</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br />        </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">extern</span><span style="color: #000000;"> IntPtr ImmGetContext(IntPtr hWnd);<br /><br />        [DllImport(</span><span style="color: #800000;">"</span><span style="color: #800000;">imm32.dll</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br />        </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">extern</span><span style="color: #000000;"> </span><span style="color: #0000ff;">bool</span><span style="color: #000000;"> ImmGetConversionStatus(IntPtr hIMC,<br />            </span><span style="color: #0000ff;">ref</span><span style="color: #000000;"> </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> conversion, </span><span style="color: #0000ff;">ref</span><span style="color: #000000;"> </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> sentence);<br /><br />        [DllImport(</span><span style="color: #800000;">"</span><span style="color: #800000;">imm32.dll</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br />        </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">extern</span><span style="color: #000000;"> </span><span style="color: #0000ff;">bool</span><span style="color: #000000;"> ImmSetConversionStatus(IntPtr hIMC, </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> conversion, </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> sentence);<br /></span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p>&nbsp;</p>

<p>
  </p><div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:57e544d9-4fac-4bf5-8edc-d9077dca9488" style="margin: 0px; padding: 0px; display: inline; float: none;"><pre style="overflow: auto; background-color: #ffffff; white-space: pre-wrap; word-wrap: break-word;"><span style="color: #000000;">            </span><span style="color: #0000ff;">foreach</span><span style="color: #000000;"> (InputLanguage iL </span><span style="color: #0000ff;">in</span><span style="color: #000000;"> InputLanguage.InstalledInputLanguages)<br />            {<br />                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (iL.LayoutName </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">中文（简体）-搜狗拼音输入法</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br />                {<br />                    InputLanguage.CurrentInputLanguage </span><span style="color: #000000;">=</span><span style="color: #000000;"> iL;<br />                    </span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />                }<br />            }<br />            IntPtr prt </span><span style="color: #000000;">=</span><span style="color: #000000;"> ImmGetContext(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.Handle);<br />            </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> iMode </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">1033</span><span style="color: #000000;">;<br />            </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> iSentence </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">;<br />            </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #000000;">!</span><span style="color: #000000;">ImmSetConversionStatus(prt, iMode, iSentence))<br />            {<br />                MessageBox.Show(</span><span style="color: #800000;">"</span><span style="color: #800000;">change error</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br />            }</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>
<p>&nbsp;</p>

<p>这样就能把输入法确定为搜狗拼音，且为全角的数字符号和英文，且标点符号为中文标点。</p>

<p>附2：</p>

<p>日文输入法的值</p>

<p>日文输入法的假名和全半角模式由mode值控制</p>

<table width="400" border="1" cellpadding="2" cellspacing="0"><tr>
      <td width="200" valign="top">模式</td>

      <td width="200" valign="top">mode 值</td>
    </tr>

    <tr>
      <td width="200" valign="top">DirectInput</td>

      <td width="200" valign="top">25</td>
    </tr>

    <tr>
      <td width="200" valign="top">Hiragana</td>

      <td width="200" valign="top">25</td>
    </tr>

    <tr>
      <td width="200" valign="top">Full Width Katakana</td>

      <td width="200" valign="top">27</td>
    </tr>

    <tr>
      <td width="200" valign="top">Full Width Alphanumeric</td>

      <td width="200" valign="top">24</td>
    </tr>

    <tr>
      <td width="200" valign="top">Half Width Katakana</td>

      <td width="200" valign="top">19</td>
    </tr>

    <tr>
      <td width="200" valign="top">Half Width Alphanumeric</td>

      <td width="200" valign="top">16</td>
    </tr>
  </table>

<p>&nbsp;</p>

<p>当用汉字的转化模式由 sentence 的值控制</p>

<table width="400" border="1" cellpadding="2" cellspacing="0"><tr>
      <td width="200" valign="top">模式</td>

      <td width="200" valign="top">值</td>
    </tr>

    <tr>
      <td width="200" valign="top">般</td>

      <td width="200" valign="top">8</td>
    </tr>

    <tr>
      <td width="200" valign="top">名</td>

      <td width="200" valign="top">1</td>
    </tr>

    <tr>
      <td width="200" valign="top">话</td>

      <td width="200" valign="top">16</td>
    </tr>

    <tr>
      <td width="200" valign="top">无</td>

      <td width="200" valign="top">0</td>
    </tr>
  </table>

<p>&nbsp;</p>

<p>附三：</p>

<p>棒子国输入法&#8230;&#8230;&#8230;没有用过，省略了吧</p><img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1608633.html?type=1" width="1" height="1" alt=""/><p>评论: 9　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/23/1608633.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/23/1608633.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56855/" target="_blank">NDepend 3.0已与Visual Studio集成</a><span style="color:gray">(2010-02-10 16:17)</span><br/>· <a href="http://news.cnblogs.com/n/56854/" target="_blank">Ruby in Steel 1.5发布，去除IronRuby支持</a><span style="color:gray">(2010-02-10 16:14)</span><br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>让你的控件舞动起来</title><link>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/20/1607035.html</link><dc:creator>亚历山大同志</dc:creator><author>亚历山大同志</author><pubDate>Fri, 20 Nov 2009 08:49:00 GMT</pubDate><guid>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/20/1607035.html</guid><description><![CDATA[<p>阅读: 2189 评论: 8 作者: <a href="http://www.cnblogs.com/Alexander-Lee/" target="_blank">亚历山大同志</a> 发表于 2009-11-20 16:49 <a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/20/1607035.html" target="_blank">原文链接</a></p><p>最近有个需求是需要窗体上要有很炫的效果，比如动画划过的panel，跟随鼠标移动的动画，动画扩大缩小的panel，诸如此类，如果单独写这些效果一是要被烦死，二是窗体内的代码会一团糟，所以弄了个指挥其他控件移动变形的控件。</p>
<p>使用方法很简单，首先把这个控件拖到窗体</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/8d828e4c0304_EBA1/image_2.png" target="_blank"><img title="image" style="border: 0px none ; display: inline;" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/8d828e4c0304_EBA1/image_thumb.png" width="191" border="0" height="130" /></a> </p>
<p>然后在需要移动其他控件的时候，比如我想在窗体上让一个按钮移动到鼠标当前点击的位置，那么只需要在窗体的mouse_click事件里这么写：</p>
<div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:7417a64c-339d-4e7a-a9c2-9b8841c2675d" style="margin: 0px; padding: 0px; display: inline; float: none;">
<pre style="overflow: auto; background-color: #ffffff; white-space: pre-wrap; word-wrap: break-word;"><span style="color: #000000;"> </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> </span><span style="color: #0000ff;">void</span><span style="color: #000000;"> Form1_MouseClick(</span><span style="color: #0000ff;">object</span><span style="color: #000000;"> sender, MouseEventArgs e)<br />
{<br />
trans.MoveTo(button1.Location, e.Location, button1,</span><span style="color: #800080;">10</span><span style="color: #000000;">);<br />
}</span></pre>
<!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>
<p>这样当你在窗体上点击鼠标左键的时候，按钮就会跟着你的鼠标跑啦。</p>
<p>效果如下，由于屏幕录像的原因效果很粗糙</p>
<p> 
</p><center><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://active.macromedia.com/flash5/cabs/swflash.cab#version=7,0,0,0" width="797" height="773">
<param name="movie" value="http://files.cnblogs.com/Alexander-Lee/movingmouse.xml" />
<param name="play" value="true" />
<param name="loop" value="false" />
<param name="wmode" value="transparent" />
<param name="quality" value="low" />
<embed src="http://files.cnblogs.com/Alexander-Lee/movingmouse.xml" quality="low" loop="false" wmode="transparent" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="797" height="773">

</object></center>

<p>&nbsp;</p>
<p>&nbsp;</p>
<p>当然不止能让控件移动，改变大小的动画也行，这些动画都是缓动的，也就是开始很快，然后慢慢变慢直到停止。接下来我们来看看是如何实现这些效果的。首先动画的原理大家都知道是视觉暂留原理，由于GDI+的绘图很繁重，暂时无法实现24帧每秒的完美动画，所以我们暂定为20帧每秒。而驱动动画的肯定是Timmer控件了，所以这里Timmer的间隔时间为50ms。</p>
<p>所以第一步我们是新建一个自动控件。并拖入一个Timmer控件，注意，是winform的Timmer，只有这个Timmer的事件里操作窗体控件不用处理线程的问题。</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/8d828e4c0304_EBA1/image_4.png" target="_blank"><img title="image" style="border: 0px none ; display: inline;" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/8d828e4c0304_EBA1/image_thumb_1.png" width="172" border="0" height="117" /></a> <a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/8d828e4c0304_EBA1/image_6.png" target="_blank"><img title="image" style="border: 0px none ; display: inline;" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/8d828e4c0304_EBA1/image_thumb_2.png" width="187" border="0" height="138" /></a> </p>
<p>有的时候可能需要移动和变形的是多个控件，我们将控件的移动行为抽象为一个行为的对象：</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/8d828e4c0304_EBA1/image_8.png" target="_blank"><img title="image" style="border: 0px none ; display: inline;" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/8d828e4c0304_EBA1/image_thumb_3.png" width="282" border="0" height="135" /></a> </p>
<p>移动和变形的数据都是两个int的元组，所以用一个类Data来抽象</p>
<p>&nbsp;</p>
<div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:3179bc3f-3b20-4ac4-b1ce-6dc126707261" style="margin: 0px; padding: 0px; display: inline; float: none;">
<pre style="overflow: auto; background-color: #ffffff; white-space: pre-wrap; word-wrap: break-word;"><span style="color: #000000;"> </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Data<br />
{<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> X { </span><span style="color: #0000ff;">get</span><span style="color: #000000;">; </span><span style="color: #0000ff;">set</span><span style="color: #000000;">; }<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> Y { </span><span style="color: #0000ff;">get</span><span style="color: #000000;">; </span><span style="color: #0000ff;">set</span><span style="color: #000000;">; }<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Data(</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> x, </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> y)<br />
{<br />
X </span><span style="color: #000000;">=</span><span style="color: #000000;"> x;<br />
Y </span><span style="color: #000000;">=</span><span style="color: #000000;"> y;<br />
}<br />
}</span></pre>
<!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>
<p>由于数据不知道是变形还是位移，所以用一个Action来把为控件赋值的操作独立出来，为了减少在Timmer的事件里的计算，加快速度，所以在移动和变形前就计算好每一个步骤的值，这些值放在Steps中，好了，接下来为Item增加计算所有步骤的方法：</p>
<p>&nbsp;</p>
<div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:1d2182d1-4e1d-4ec1-bb50-296ac2c1004f" style="margin: 0px; padding: 0px; display: inline; float: none;">
<pre style="overflow: auto; background-color: #ffffff; white-space: pre-wrap; word-wrap: break-word;"><span style="color: #000000;"> </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">void</span><span style="color: #000000;"> Compute(</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> Step)<br />
{<br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> XDirection </span><span style="color: #000000;">=</span><span style="color: #000000;"> To.X.CompareTo(From.X);<br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> YDirection </span><span style="color: #000000;">=</span><span style="color: #000000;"> To.Y.CompareTo(From.Y);<br />
Steps.Add(From);<br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> x </span><span style="color: #000000;">=</span><span style="color: #000000;"> From.X;<br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> y </span><span style="color: #000000;">=</span><span style="color: #000000;"> From.Y;<br />
</span><span style="color: #0000ff;">double</span><span style="color: #000000;"> itemX </span><span style="color: #000000;">=</span><span style="color: #000000;"> ((</span><span style="color: #0000ff;">double</span><span style="color: #000000;">)Math.Abs(From.X </span><span style="color: #000000;">-</span><span style="color: #000000;"> To.X)) </span><span style="color: #000000;">/</span><span style="color: #000000;"> StepToItem(Step);<br />
</span><span style="color: #0000ff;">double</span><span style="color: #000000;"> itemY </span><span style="color: #000000;">=</span><span style="color: #000000;"> ((</span><span style="color: #0000ff;">double</span><span style="color: #000000;">)Math.Abs(From.Y </span><span style="color: #000000;">-</span><span style="color: #000000;"> To.Y)) </span><span style="color: #000000;">/</span><span style="color: #000000;"> StepToItem(Step);<br />
</span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> i </span><span style="color: #000000;">=</span><span style="color: #000000;"> Step; i </span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">; i</span><span style="color: #000000;">--</span><span style="color: #000000;">)<br />
{<br />
</span><span style="color: #0000ff;">double</span><span style="color: #000000;"> offsetX </span><span style="color: #000000;">=</span><span style="color: #000000;"> (i </span><span style="color: #000000;">*</span><span style="color: #000000;"> </span><span style="color: #800080;">2</span><span style="color: #000000;"> </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #800080;">1</span><span style="color: #000000;">) </span><span style="color: #000000;">*</span><span style="color: #000000;"> itemX;<br />
</span><span style="color: #0000ff;">double</span><span style="color: #000000;"> offsetY </span><span style="color: #000000;">=</span><span style="color: #000000;"> (i </span><span style="color: #000000;">*</span><span style="color: #000000;"> </span><span style="color: #800080;">2</span><span style="color: #000000;"> </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #800080;">1</span><span style="color: #000000;">) </span><span style="color: #000000;">*</span><span style="color: #000000;"> itemY;<br />
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (XDirection </span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">)<br />
{<br />
x </span><span style="color: #000000;">=</span><span style="color: #000000;"> (</span><span style="color: #0000ff;">int</span><span style="color: #000000;">)(x </span><span style="color: #000000;">+</span><span style="color: #000000;"> offsetX);<br />
}<br />
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (XDirection </span><span style="color: #000000;">&lt;</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">)<br />
{<br />
x </span><span style="color: #000000;">=</span><span style="color: #000000;"> (</span><span style="color: #0000ff;">int</span><span style="color: #000000;">)(x </span><span style="color: #000000;">-</span><span style="color: #000000;"> offsetX);<br />
}<br />
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (YDirection </span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">)<br />
{<br />
y </span><span style="color: #000000;">=</span><span style="color: #000000;"> (</span><span style="color: #0000ff;">int</span><span style="color: #000000;">)(y </span><span style="color: #000000;">+</span><span style="color: #000000;"> offsetY);<br />
}<br />
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (YDirection </span><span style="color: #000000;">&lt;</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">)<br />
{<br />
y </span><span style="color: #000000;">=</span><span style="color: #000000;"> (</span><span style="color: #0000ff;">int</span><span style="color: #000000;">)(y </span><span style="color: #000000;">-</span><span style="color: #000000;"> offsetY);<br />
}<br />
Steps.Add(</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Data(x, y));<br />
}<br />
Steps.Add(To);<br />
}</span></pre>
<!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>
<p>参数Steps是设定要计算多少个中间步骤，数值越大移动越慢，数值越小移动越快。</p>
<p>接下来在控件中增加一个list来存储需要移动的行为，并初始化</p>
<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/8d828e4c0304_EBA1/image_10.png" target="_blank"><img title="image" style="border: 0px none ; display: inline;" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/8d828e4c0304_EBA1/image_thumb_4.png" width="355" border="0" height="143" /></a> </p>
<p>然后在Timmer的事件里驱动移动的步骤：</p>
<p>&nbsp;</p>
<div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:150d9240-114d-4ec2-b916-e4d8419b2685" style="margin: 0px; padding: 0px; display: inline; float: none;">
<pre style="overflow: auto; background-color: #ffffff; white-space: pre-wrap; word-wrap: break-word;"><span style="color: #000000;"> </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> </span><span style="color: #0000ff;">void</span><span style="color: #000000;"> ProcessItems(</span><span style="color: #0000ff;">object</span><span style="color: #000000;"> sender, EventArgs e)<br />
{<br />
List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Item</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> removelist </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Item</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();<br />
</span><span style="color: #0000ff;">foreach</span><span style="color: #000000;"> (Item item </span><span style="color: #0000ff;">in</span><span style="color: #000000;"> Items)<br />
{<br />
item.MoveStep</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (item.MoveStep </span><span style="color: #000000;">&lt;</span><span style="color: #000000;"> item.Steps.Count)<br />
{<br />
item.CurrentStep </span><span style="color: #000000;">=</span><span style="color: #000000;"> item.Steps[item.MoveStep];<br />
item.Moving();<br />
}<br />
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">
{
removelist.Add(item);
}
}
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (removelist.Count </span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">)<br />
{<br />
</span><span style="color: #0000ff;">foreach</span><span style="color: #000000;"> (Item item </span><span style="color: #0000ff;">in</span><span style="color: #000000;"> removelist)<br />
{<br />
Items.Remove(item);<br />
}<br />
}<br />
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (Items.Count </span><span style="color: #000000;">&lt;</span><span style="color: #000000;"> </span><span style="color: #800080;">1</span><span style="color: #000000;"> )<br />
{<br />
ProcessTimer.Stop();<br />
}<br />
}</span></pre>
<!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>
<p>移动完成的就把项目从列表里移除。如果没有项目可以移动了就关闭timmer节约资源</p>
<p>&nbsp;</p>
<p>最后实现两个方法来启动移动和形变的过程：</p>
<p>&nbsp;</p>
<div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:31f1398e-ea88-4da4-a678-c10695df8bac" style="margin: 0px; padding: 0px; display: inline; float: none;">
<pre style="overflow: auto; background-color: #ffffff; white-space: pre-wrap; word-wrap: break-word;"><span style="color: #000000;"> </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">void</span><span style="color: #000000;"> MoveTo(Point From, Point To, Control Target, </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> Step)<br />
{<br />
Item item </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Item()<br />
{<br />
CurrentStep </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Data(From.X,From.Y),<br />
From </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Data(From.X,From.Y),<br />
To </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Data(To.X,To.Y),<br />
MoveStep </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">,<br />
Steps </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Data</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(),<br />
Target </span><span style="color: #000000;">=</span><span style="color: #000000;"> Target<br />
};<br />
item.SetValue </span><span style="color: #000000;">=</span><span style="color: #000000;"> (d, c) </span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">
{
c.Location </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Point(d.X, d.Y);<br />
};<br />
item.Compute(Step);<br />
Items.Add(item);<br />
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #000000;">!</span><span style="color: #000000;">ProcessTimer.Enabled)<br />
{<br />
ProcessTimer.Start();<br />
}<br />
}<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">void</span><span style="color: #000000;"> ScaleTo(Size From,Size To,Control Target,</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> Step)<br />
{<br />
Item item </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Item()<br />
{<br />
CurrentStep </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Data(From.Width, From.Height),<br />
From </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Data(From.Width, From.Height),<br />
To </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Data(To.Width, To.Height),<br />
MoveStep </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">,<br />
Steps </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Data</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(),<br />
Target </span><span style="color: #000000;">=</span><span style="color: #000000;"> Target<br />
};<br />
item.SetValue </span><span style="color: #000000;">=</span><span style="color: #000000;"> (d, c) </span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">
{
c.Size </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> Size(d.X, d.Y);<br />
};<br />
item.Compute(Step);<br />
Items.Add(item);<br />
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (</span><span style="color: #000000;">!</span><span style="color: #000000;">ProcessTimer.Enabled)<br />
{<br />
ProcessTimer.Start();<br />
}<br />
}</span></pre>
<!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com --></div>
<p>如果你跟着本文的步骤一起做了，那么现在就可以来尝试玩一玩这个东西了。</p>
<p>最后强调一下，一定要把窗体和控件的双缓冲都打开，不然就是眼睛被闪了，置于如何开双缓冲就不在本文范围内了</p><img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1607035.html?type=1" width="1" height="1" alt=""/><p>评论: 8　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/20/1607035.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/20/1607035.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56855/" target="_blank">NDepend 3.0已与Visual Studio集成</a><span style="color:gray">(2010-02-10 16:17)</span><br/>· <a href="http://news.cnblogs.com/n/56854/" target="_blank">Ruby in Steel 1.5发布，去除IronRuby支持</a><span style="color:gray">(2010-02-10 16:14)</span><br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>脑残的FtpWebRequest 2之事故现场重现</title><link>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/14/1603008.html</link><dc:creator>亚历山大同志</dc:creator><author>亚历山大同志</author><pubDate>Sat, 14 Nov 2009 06:37:00 GMT</pubDate><guid>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/14/1603008.html</guid><description><![CDATA[<p>阅读: 1240 评论: 7 作者: <a href="http://www.cnblogs.com/Alexander-Lee/" target="_blank">亚历山大同志</a> 发表于 2009-11-14 14:37 <a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/14/1603008.html" target="_blank">原文链接</a></p><p>鉴于上一篇POST过于抽象以至于很多人无法理解，现在用代码来说话，我们一起来重新回顾一下事故现场的情况。</p>  <p>首先在本机安装FTP软件，我这里使用的Serv-U一个用得非常广泛的Ftp Server，准备好Ftp的目录，我这里使用自己放mp3的目录</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/Prepare_ftp_dir_2.jpg" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Prepare_ftp_dir" border="0" alt="Prepare_ftp_dir" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/Prepare_ftp_dir_thumb.jpg" width="457" height="251" /></a> </p>  <p>其中有一个子目录 2 </p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/Prepare_ftp_dir2_2.jpg" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Prepare_ftp_dir2" border="0" alt="Prepare_ftp_dir2" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/Prepare_ftp_dir2_thumb.jpg" width="386" height="318" /></a> </p>  <p>我们可以看到两个目录的内容截然不同以方便我们重现事故现场。</p>  <p>第二部我们建立一个Winform项目</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/Create_project_2.jpg" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Create_project" border="0" alt="Create_project" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/Create_project_thumb.jpg" width="368" height="210" /></a> </p>  <p>之后在界面上用三个按钮来实现testCase</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/Test_Case_2.jpg" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Test_Case" border="0" alt="Test_Case" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/Test_Case_thumb.jpg" width="457" height="297" /></a> </p>  <p>&nbsp;</p>  <p>&nbsp;</p>  <p>&nbsp;</p>  <p>第三步是准备的重头戏，我们准备一个Ftp的操作类：</p>  <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:98640977-9bcf-48b4-ad30-6c4eb2709551" class="wlWriterEditableSmartContent"><pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; ">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;

namespace TestFtpWebRequest
{
    class FtpHelper
    {
        public static void Upload(string Url, string LocalPath)
        {
            FileInfo f = new FileInfo(LocalPath);
            FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(Url + "/" + f.Name);
            req.Credentials = new NetworkCredential("Test", "123456");
            req.Method = WebRequestMethods.Ftp.UploadFile;
            req.UseBinary = true;
            req.ContentLength = f.Length;
            FtpWebResponse rep = (FtpWebResponse)req.GetResponse();
            using (Stream s = req.GetRequestStream())
            {
                using (FileStream fs = f.OpenRead())
                {
                    int readcount = 0;
                    long totalread = 0;
                    byte[] buffer = new byte[1024];
                    while (true)
                    {
                        readcount = fs.Read(buffer, 0, 1024);
                        totalread += readcount;
                        s.Write(buffer, 0, readcount);
                        if (totalread &gt;= f.Length)
                        {
                            break;
                        }
                    }

                }
            }
        }
        public static string[] List(string Url)
        {
            List&lt;string&gt; rs = new List&lt;string&gt;();
            FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(Url);
            req.Credentials = new NetworkCredential("Test", "123456");
            req.Method = WebRequestMethods.Ftp.ListDirectory;
            FtpWebResponse rep = (FtpWebResponse)req.GetResponse();
            long len = rep.ContentLength;
            using (Stream s = rep.GetResponseStream())
            {
                MemoryStream ms = new MemoryStream();
                int readcount = 0;
                long totalcount = 0;
                byte[] buffer = new byte[1024];
                while (true)
                {
                    readcount = s.Read(buffer, 0, 1024);
                    totalcount += readcount;
                    ms.Write(buffer, 0, readcount);
                    if (totalcount &gt;= len)
                    {
                        break;
                    }
                }
                s.Close();
                rep.Close();
                string str = Encoding.Default.GetString(ms.ToArray());
                StringReader sr = new StringReader(str);
                string line = string.Empty;
                while ((line = sr.ReadLine()) != null)
                {
                    rs.Add(line);
                }
            }
            return rs.ToArray();
        }
    }
}
</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p>这里准备了两个操作方法，一个是读取文件列表，一个是上传文件</p>

<p>最后在按钮里写上调用的方法</p>

<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:DFDE9937-D816-47f4-A306-7B60D5CE5AC0:acf009de-cea7-476a-b9ae-03b8eac7f38f" class="wlWriterEditableSmartContent"><pre class="brush: csharp; gutter: true; first-line: 1; tab-size: 4;  toolbar: true; ">using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TestFtpWebRequest
{
    public partial class Form1 : Form
    {
        const string Path1 = @"D:\MyDocument\test.jpg";
        const string Path2 = @"D:\MyDocument\yoxi.jpg";
        const string FtpUrl = "ftp://192.168.212.102";
        const string FtpUrl2 = "ftp://192.168.212.102/2";

        public Form1()
        {
            InitializeComponent();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            textBox1.Text = string.Empty;
            string[] files = FtpHelper.List(FtpUrl);

            textBox1.Text = "file count:" + files.Length + "\r\n";
            foreach (string s in files)
            {
                textBox1.Text += "ftp:" + s + "\r\n";
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            FtpHelper.Upload(FtpUrl2, Path1);
            MessageBox.Show("up ok!");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            FtpHelper.Upload(FtpUrl2, Path2);
            MessageBox.Show("up ok!");
        }
    }
}
</pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p>好了，根据两个ftp的方法大家可以看到，从表面上两个方法应该是独立的，不管在什么时候，我如果按列表的按钮都应该返回Ftp根目录的文件列表出来。但是实际的执行结果，我们拭目以待。</p>

<p>首先我们执行程序，点击列表按钮(List with no upload)，这个时候我们能够看到返回的确实是根目录的文件</p>

<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_2.png" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_thumb.png" width="398" height="250" /></a>&nbsp;</p>

<p>现在我们继续点击 FirstUpload，按钮，猜猜结果怎么样? 报错了：</p>

<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_4.png" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_thumb_1.png" width="483" height="178" /></a></p>

<p>路径明明是对的，为什么报错？大家可以自己想想</p>

<p>接下来我们把顺序换一下。重新执行程序，这次先点击Firstupload，结果上传成功，结果如下</p>

<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_6.png" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_thumb_2.png" width="363" height="231" /></a> </p>

<p>好，这个时候我们再点击列表按钮，本来应该显示根目录内容的，结果却显示的：</p>

<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_8.png" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_thumb_3.png" width="378" height="239" /></a>&nbsp; </p>

<p>这下看明白了没？好的，接下来我们调整一下Ftp的设置，现在Ftp账号的设置如下：</p>

<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_10.png" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_thumb_4.png" width="397" height="138" /></a> </p>

<p>我们现在把将用户锁定于主目录的勾去掉：</p>

<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_12.png" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_thumb_5.png" width="396" height="141" /></a> </p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>如此这般，好了，现在我们再次执行程序。</p>

<p>先点击列表,然后再点击上传，看看，没报错，成功了：</p>

<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_14.png" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_thumb_6.png" width="391" height="246" /></a> </p>

<p>---------------------------------------------------------</p>

<p>一开始我怀疑是因为KeepAlive保持了链接造成的，因为这个结果非常像是每一个Request都复用了连接，所以我两个方法都加上了KeepAlive=false</p>

<p>然后恢复Serv-U的设置，将锁定用户于主目录的勾选上。</p>

<p>执行程序，点击列表，再点击上传，成功了，貌似没问题了吧。不过不要高兴得太早，这个时候再点击一次列表，看，报错了：</p>

<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_16.png" target="_blank"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/FtpWebRequest2_CCEA/image_thumb_7.png" width="569" height="209" /></a> </p>

<p>到现在为止，我应该对事故的由来，前因后果说得很清楚了。</p>

<p>这里我总结出了几点问题。</p>

<p>1.不管是不是要复用底层的链接，但是在语义上的一致性是需要保证的，一个Request，既然用url :Ftp://ip/创建出来的，那么就应该是操作Ftp的根而不是其他目录，如果这个都不能保证，那么谁还能信任这样的一个工具？更不用说多线程的环境下工作会如何了。</p>

<p>2.为了安全性，大部分ftp都会锁定用户到主目录，一个ftpclient怎么能够依赖于服务端的设置工作？无论是谁做出这种脑残设定都是不对的。</p>

<p>3.KeepAlive禁用后，居然同样的过程执行都会报错，不可理喻。</p>

<p>具体问题处在哪里，等我下次分析了。</p><img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1603008.html?type=1" width="1" height="1" alt=""/><p>评论: 7　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/14/1603008.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/14/1603008.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56855/" target="_blank">NDepend 3.0已与Visual Studio集成</a><span style="color:gray">(2010-02-10 16:17)</span><br/>· <a href="http://news.cnblogs.com/n/56854/" target="_blank">Ruby in Steel 1.5发布，去除IronRuby支持</a><span style="color:gray">(2010-02-10 16:14)</span><br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>惊天大Bug？让人呕血的FtpWebRequest</title><link>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/13/FtpwebRequestRant.html</link><dc:creator>亚历山大同志</dc:creator><author>亚历山大同志</author><pubDate>Fri, 13 Nov 2009 09:10:00 GMT</pubDate><guid>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/13/FtpwebRequestRant.html</guid><description><![CDATA[<p>阅读: 2081 评论: 15 作者: <a href="http://www.cnblogs.com/Alexander-Lee/" target="_blank">亚历山大同志</a> 发表于 2009-11-13 17:10 <a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/13/FtpwebRequestRant.html" target="_blank">原文链接</a></p><p>本来以为2.0开始内置了FtpWebRequest，以后不用再受没有更新保障的第三方Ftp类库的限制，结果今天遇到的问题，让我呕血三升不得其解。看来又得自己写FtpClient的类了。言归正传，先说问题</p>  <p>以前用到Ftp上传很多都是一次性的操作，所以如果:</p>  <p>FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create("url");</p>  <p>之 后的话就可以上传，下载，或者什么的，之后就直接退出了事。结果现在的需求会涉及很多比较具有持续性的操作，比如进入一个根目录，然后list，判断是否 存在一个目录，如果存在就cd进入，不存在就md创建这个目录，之后进入，再上传文件到目录中。这个时候麻烦产生了。一般来说为了安全性的原因，设置 FTP的时候都设置了锁定用户在主目录的选项。比如Serv-U如下：</p>  <p><a target="_blank" href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/BugFtpWebRequest_EEE8/image_2.png"><img title="image" style="border-width: 0px; display: inline;" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/BugFtpWebRequest_EEE8/image_thumb.png" width="325" border="0" height="213" /></a> </p>  <p>这个时候第一次执行，很好，一点问题都没有，但是第二次执行的时候麻烦就来了。</p>  <p>比如Ftp的根url为 <a target="_blank" href="ftp://xx.xx.xx.xx/">Ftp://xx.xx.xx.xx/</a> 要进入的目录为test，第一次在FtpWebRequest.Create("<a target="_blank" href="ftp://xx.xx.xx.xx/">Ftp://xx.xx.xx.xx/</a>");的时候，我们list得到的是根目录的内容，但是在上传完成后进行第二次操作，这个时候创建FtpWebRequest对象的url仍然是 <a target="_blank" href="ftp://xx.xx.xx.xx/">Ftp://xx.xx.xx.xx/</a> 但是再执行list的时候取出的确是test目录下的文件列表！！</p>  <p>之后为了测试我去掉了 <a target="_blank" href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/BugFtpWebRequest_EEE8/image_4.png"><img title="image" style="border-width: 0px; display: inline;" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/BugFtpWebRequest_EEE8/image_thumb_1.png" width="189" border="0" height="69" /></a> 之后执行就一点问题都没有了。</p>  <p>但 是注意，这里的两次操作是两个不同的FtpWebRequest对象，却保持了同一个操作的Session。且让人郁闷的是，FtpWebRequest 没有提供任何显示关闭连接的方法，也没有任何改变工作目录的方法，即使是新建的FtpWebRequest对象使用了不同的url，仍然不会改变其当初的 工作目录，后来查了一下Serv-U的日志，发现根本就没法送改变工作目录的指令&#8230;&#8230;&#8230;</p>  <p>为了FtpWebRequest的对象不保持连 接的上下文，我把KeepAlive属性设为false，结果出现了第二个让我呕血的问题。当第二次执行操作的时候，报错了，如果是连本机的FTP则报返 回226 transfercomplete的异常，如果是远程的ftp则报无法访问已经释放的对象&#8230;&#8230;&#8230;&#8230;&#8230;</p>  <p>不知道如此一个脑残的东西是如何通过层层审核进入.NET的类库的。呕血的FtpWebRequest</p>  <p>如果有兴趣的可以自己实验一下，验证一下结果，测试的case为：</p>  <p>while（true）{</p>  <p>创建FtpwebRequest</p>  <p>列表目录</p>  <p>创建FtpWe</p>  <p>上传文件</p>  <p>此处打断点</p>  <p>}</p>  <p>还可以通过Serv-U看看其中的log，看看到底发送了些什么ftp指令</p>  如果有达人发现是我哪里搞错了也请告之，万分感谢。<img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1602644.html?type=1" width="1" height="1" alt=""/><p>评论: 15　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/13/FtpwebRequestRant.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/13/FtpwebRequestRant.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56855/" target="_blank">NDepend 3.0已与Visual Studio集成</a><span style="color:gray">(2010-02-10 16:17)</span><br/>· <a href="http://news.cnblogs.com/n/56854/" target="_blank">Ruby in Steel 1.5发布，去除IronRuby支持</a><span style="color:gray">(2010-02-10 16:14)</span><br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>用edas写一个简单的http Server，扩展http协议的处理器</title><link>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/11/1601391.html</link><dc:creator>亚历山大同志</dc:creator><author>亚历山大同志</author><pubDate>Wed, 11 Nov 2009 15:04:00 GMT</pubDate><guid>http://www.cnblogs.com/Alexander-Lee/archive/2009/11/11/1601391.html</guid><description><![CDATA[<p>阅读: 1158 评论: 11 作者: <a href="http://www.cnblogs.com/Alexander-Lee/" target="_blank">亚历山大同志</a> 发表于 2009-11-11 23:04 <a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/11/1601391.html" target="_blank">原文链接</a></p><p>为了说明一下基础tcp开发库是如何扩展来处理上层协议的，我这里用一个简单到极点的Http Server来作为例子。这个例子会处理发到特定端口的所有http请求，并返回显示Hello world的网页。</p>  <p>由于是一个很简单的例子，所以我们并不需要解析完整的Http协议，当然我们是能够很快构建一个http处理器，毕竟这是一个基于文本行的协议，不过即使这样还是需要很大的篇幅，所以我们只需要处理其中一小部份。</p>  <p>首先我们来看看Http的request。http的请求是一串文本，由多个行组成，每行都是key value形式的，第一行表示了请求的方法和路径，由空格隔开，后面的是请求的头，由冒号隔开，不过其中的内容表示什么意思对我们来说没什么意义，我们在这里也不打算处理，我们把它们存在一个hash表里，等待更高级的处理器来处理。</p>  <p>所以首先我们先建立一个类，实现IProcessor接口：</p>  <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:8c61ce88-9bfb-4231-b783-35b70c24a1ad" class="wlWriterEditableSmartContent"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #000000;">    </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> HttpProcessor : IProcessor
    {
        </span><span style="color: #0000FF;">#region</span><span style="color: #000000;"> IProcessor 鎴愬憳</span><span style="color: #000000;">

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> Init(IWorkingSocket Sock)
        {
            </span><span style="color: #0000FF;">throw</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> NotImplementedException();
        }

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> NextProcessor(IProcessor NextProcessor)
        {
            </span><span style="color: #0000FF;">throw</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> NotImplementedException();
        }

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> PushData(</span><span style="color: #0000FF;">byte</span><span style="color: #000000;">[] Data, </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> ReadCount)
        {
            </span><span style="color: #0000FF;">throw</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> NotImplementedException();
        }

        </span><span style="color: #0000FF;">#endregion</span><span style="color: #000000;">

        </span><span style="color: #0000FF;">#region</span><span style="color: #000000;"> IDisposable 鎴愬憳</span><span style="color: #000000;">

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> Dispose()
        {
            </span><span style="color: #0000FF;">throw</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> NotImplementedException();
        }

        </span><span style="color: #0000FF;">#endregion</span><span style="color: #000000;">
    }</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p>&#160;</p>

<p>根据前面的分析我们需要在其中用一个HashTable来存储http的请求头信息。</p>

<p>在每一次得到一行数据的时候就分析，是头一行还是header的行。然后将其插入hashtable，如果得到的是一个空行，那么就表明请求结束了，那么我们就将一段html发送回去。</p>

<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:891b6b51-9e08-40f4-a806-e67d4ef44c27" class="wlWriterEditableSmartContent"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #000000;">    </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> HttpProcessor : IProcessor
    {
        </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> Dictionary</span><span style="color: #000000;">&lt;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">, </span><span style="color: #0000FF;">string</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> httpHeader;

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> HttpProcessor()
        {
            httpHeader </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Dictionary</span><span style="color: #000000;">&lt;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">, </span><span style="color: #0000FF;">string</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();
        }

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">event</span><span style="color: #000000;"> Action</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">IWorkingSocket,Dictionary</span><span style="color: #000000;">&lt;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">, </span><span style="color: #0000FF;">string</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;"> OnRequest;

        </span><span style="color: #0000FF;">#region</span><span style="color: #000000;"> IProcessor 成员</span><span style="color: #000000;">

        </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> IWorkingSocket Conn;

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> Init(IWorkingSocket Sock)
        {
            Conn </span><span style="color: #000000;">=</span><span style="color: #000000;"> Sock;
        }

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> NextProcessor(IProcessor NextProcessor)
        {
            </span><span style="color: #008000;">//</span><span style="color: #008000;">如果没有下级处理器就留空</span><span style="color: #008000;">
</span><span style="color: #000000;">        }

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> PushData(</span><span style="color: #0000FF;">byte</span><span style="color: #000000;">[] Data, </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> ReadCount)
        {
            </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> line </span><span style="color: #000000;">=</span><span style="color: #000000;"> Encoding.ASCII.GetString(Data, </span><span style="color: #800080;">0</span><span style="color: #000000;">, ReadCount);
            </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (line.Equals(</span><span style="color: #800000;">"</span><span style="color: #800000;">\r\n</span><span style="color: #800000;">"</span><span style="color: #000000;">))
            {
                </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (OnRequest </span><span style="color: #000000;">!=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">)
                {
                    OnRequest(Conn, httpHeader);
                }
            }
            </span><span style="color: #0000FF;">string</span><span style="color: #000000;">[] temp </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">;   
            </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (line.Split(</span><span style="color: #800000;">'</span><span style="color: #800000;">:</span><span style="color: #800000;">'</span><span style="color: #000000;">).Length</span><span style="color: #000000;">&gt;</span><span style="color: #800080;">1</span><span style="color: #000000;">)
            {
                temp </span><span style="color: #000000;">=</span><span style="color: #000000;"> line.Split(</span><span style="color: #800000;">'</span><span style="color: #800000;">:</span><span style="color: #800000;">'</span><span style="color: #000000;">);
                httpHeader.Add(temp[</span><span style="color: #800080;">0</span><span style="color: #000000;">], temp[</span><span style="color: #800080;">1</span><span style="color: #000000;">]);
                </span><span style="color: #0000FF;">return</span><span style="color: #000000;">;
            }
            </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (line.Split(</span><span style="color: #800000;">'</span><span style="color: #800000;"> </span><span style="color: #800000;">'</span><span style="color: #000000;">).Length </span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> </span><span style="color: #800080;">1</span><span style="color: #000000;">)
            {
                temp </span><span style="color: #000000;">=</span><span style="color: #000000;"> line.Split(</span><span style="color: #800000;">'</span><span style="color: #800000;"> </span><span style="color: #800000;">'</span><span style="color: #000000;">);
                httpHeader.Add(temp[</span><span style="color: #800080;">0</span><span style="color: #000000;">], temp[</span><span style="color: #800080;">1</span><span style="color: #000000;">]);
                </span><span style="color: #0000FF;">return</span><span style="color: #000000;">;
            }
        }

        </span><span style="color: #0000FF;">#endregion</span><span style="color: #000000;">

        </span><span style="color: #0000FF;">#region</span><span style="color: #000000;"> IDisposable 回收资源</span><span style="color: #000000;">

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> Dispose()
        {
            httpHeader.Clear();
            Conn </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">;
        }
        </span><span style="color: #0000FF;">#endregion</span><span style="color: #000000;">
    }</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p>&#160;</p>

<p>ok，这样子后我们在处理OnRequest事件的时候就能够接收到一个Dictionary对象，里面就是所有http的头信息，如果我们不关系其中的内容就可以直接在这个事件里返回数据了。</p>

<p>最后的结果：</p>

<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:6af75ae5-b81e-4d08-8783-0f8b5e923a45" class="wlWriterEditableSmartContent"><pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;"><span style="color: #0000FF;">using</span><span style="color: #000000;"> System;
</span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Collections.Generic;
</span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Linq;
</span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Text;
</span><span style="color: #0000FF;">using</span><span style="color: #000000;"> System.Net;
</span><span style="color: #0000FF;">using</span><span style="color: #000000;"> org.Alexander.EDAS;

</span><span style="color: #0000FF;">namespace</span><span style="color: #000000;"> EdasServer
{
    </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> Program
    {
        </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> Main(</span><span style="color: #0000FF;">string</span><span style="color: #000000;">[] args)
        {
            Acceptor acp </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Acceptor(</span><span style="color: #800080;">8888</span><span style="color: #000000;">);
            acp.OnError </span><span style="color: #000000;">=</span><span style="color: #000000;"> (ex, str) </span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">
            {
                </span><span style="color: #008000;">//</span><span style="color: #008000;">TO DO:To handle listenner's error</span><span style="color: #008000;">
</span><span style="color: #000000;">            };
            acp.Accepted </span><span style="color: #000000;">=</span><span style="color: #000000;"> (sock,id,buffersize) </span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">
            {
                AsyncSocket sk </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> AsyncSocket(sock, buffersize);
                sk.ID </span><span style="color: #000000;">=</span><span style="color: #000000;"> id;
                sk.OnError </span><span style="color: #000000;">+=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Action</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Exception, </span><span style="color: #0000FF;">string</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(sk_OnError);
                sk.Disconnected </span><span style="color: #000000;">+=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Action</span><span style="color: #000000;">&lt;</span><span style="color: #0000FF;">long</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(sk_Disconnected);
                TokenProcessor Proc </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> TokenProcessor(</span><span style="color: #800080;">0x0A</span><span style="color: #000000;">);
                sk.Processor </span><span style="color: #000000;">=</span><span style="color: #000000;"> Proc;
                HttpProcessor httpProc </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> HttpProcessor();
                httpProc.OnRequest </span><span style="color: #000000;">+=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Action</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">IWorkingSocket, Dictionary</span><span style="color: #000000;">&lt;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">, </span><span style="color: #0000FF;">string</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">(httpProc_OnRequest);
                Proc.NextProcessor(httpProc);
                sk.WaitReceive();
            };
            acp.WaitAsyncAccept();
            Console.ReadKey();
        }

        </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> httpProc_OnRequest(IWorkingSocket arg1, Dictionary</span><span style="color: #000000;">&lt;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">, </span><span style="color: #0000FF;">string</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> arg2)
        {
            StringBuilder html</span><span style="color: #000000;">=</span><span style="color: #0000FF;">new</span><span style="color: #000000;"> StringBuilder();
            html.Append(</span><span style="color: #800000;">"</span><span style="color: #800000;">&lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;test&lt;/TITLE&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;H3&gt;Hello world&lt;/H3&gt;&lt;/BODY&gt;&lt;/HTML&gt;</span><span style="color: #800000;">"</span><span style="color: #000000;">);
            StringBuilder str </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> StringBuilder();
            str.Append(</span><span style="color: #800000;">"</span><span style="color: #800000;">HTTP /1.1 200 OK\r\n</span><span style="color: #800000;">"</span><span style="color: #000000;">);
            str.Append(</span><span style="color: #800000;">"</span><span style="color: #800000;">Date:</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> DateTime.Now.ToLongDateString()</span><span style="color: #000000;">+</span><span style="color: #800000;">"</span><span style="color: #800000;">\r\n</span><span style="color: #800000;">"</span><span style="color: #000000;">);
            str.Append(</span><span style="color: #800000;">"</span><span style="color: #800000;">Server: Edas Server(win32)\r\n</span><span style="color: #800000;">"</span><span style="color: #000000;">);
            str.Append(</span><span style="color: #800000;">"</span><span style="color: #800000;">Content-Length: </span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> html.Length</span><span style="color: #000000;">+</span><span style="color: #800000;">"</span><span style="color: #800000;">\r\n</span><span style="color: #800000;">"</span><span style="color: #000000;">);
            str.Append(</span><span style="color: #800000;">"</span><span style="color: #800000;">Content-Type: text/html\r\n</span><span style="color: #800000;">"</span><span style="color: #000000;">);
            </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> Data </span><span style="color: #000000;">=</span><span style="color: #000000;"> str.ToString() </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">\r\n</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> html.ToString();
            arg1.SendToQueue(Encoding.ASCII.GetBytes(Data));
            arg1.Disconnect();
        }
        </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> sk_Disconnected(</span><span style="color: #0000FF;">long</span><span style="color: #000000;"> obj)
        {
            </span><span style="color: #008000;">//</span><span style="color: #008000;">TO DO:To handle disconnect event</span><span style="color: #008000;">
</span><span style="color: #000000;">        }
        </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> Proc_OnLine(IWorkingSocket arg1, </span><span style="color: #0000FF;">byte</span><span style="color: #000000;">[] arg2)
        {
            arg1.SendToQueue(arg2);
        }
        </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> sk_OnError(Exception arg1, </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> arg2)
        {
            </span><span style="color: #008000;">//</span><span style="color: #008000;">TO DO:Process errors</span><span style="color: #008000;">
</span><span style="color: #000000;">        }
    }

    </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> HttpProcessor : IProcessor
    {
        </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> Dictionary</span><span style="color: #000000;">&lt;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">, </span><span style="color: #0000FF;">string</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> httpHeader;

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> HttpProcessor()
        {
            httpHeader </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Dictionary</span><span style="color: #000000;">&lt;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">, </span><span style="color: #0000FF;">string</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();
        }

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">event</span><span style="color: #000000;"> Action</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">IWorkingSocket,Dictionary</span><span style="color: #000000;">&lt;</span><span style="color: #0000FF;">string</span><span style="color: #000000;">, </span><span style="color: #0000FF;">string</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;"> OnRequest;

        </span><span style="color: #0000FF;">#region</span><span style="color: #000000;"> IProcessor 鎴愬憳</span><span style="color: #000000;">

        </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> IWorkingSocket Conn;

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> Init(IWorkingSocket Sock)
        {
            Conn </span><span style="color: #000000;">=</span><span style="color: #000000;"> Sock;
        }

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> NextProcessor(IProcessor NextProcessor)
        {
            </span><span style="color: #008000;">//</span><span style="color: #008000;">濡傛灉鏆傛椂娌℃湁涓嬬骇澶勭悊鍣ㄧ殑鏃跺€欑暀绌?</span><span style="color: #008000;">
</span><span style="color: #000000;">        }

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> PushData(</span><span style="color: #0000FF;">byte</span><span style="color: #000000;">[] Data, </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> ReadCount)
        {
            </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> line </span><span style="color: #000000;">=</span><span style="color: #000000;"> Encoding.ASCII.GetString(Data, </span><span style="color: #800080;">0</span><span style="color: #000000;">, ReadCount);
            </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (line.Equals(</span><span style="color: #800000;">"</span><span style="color: #800000;">\r\n</span><span style="color: #800000;">"</span><span style="color: #000000;">))
            {
                </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (OnRequest </span><span style="color: #000000;">!=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">)
                {
                    OnRequest(Conn, httpHeader);
                }
            }
            </span><span style="color: #0000FF;">string</span><span style="color: #000000;">[] temp </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">;   
            </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (line.Split(</span><span style="color: #800000;">'</span><span style="color: #800000;">:</span><span style="color: #800000;">'</span><span style="color: #000000;">).Length</span><span style="color: #000000;">&gt;</span><span style="color: #800080;">1</span><span style="color: #000000;">)
            {
                temp </span><span style="color: #000000;">=</span><span style="color: #000000;"> line.Split(</span><span style="color: #800000;">'</span><span style="color: #800000;">:</span><span style="color: #800000;">'</span><span style="color: #000000;">);
                httpHeader.Add(temp[</span><span style="color: #800080;">0</span><span style="color: #000000;">], temp[</span><span style="color: #800080;">1</span><span style="color: #000000;">]);
                </span><span style="color: #0000FF;">return</span><span style="color: #000000;">;
            }
            </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (line.Split(</span><span style="color: #800000;">'</span><span style="color: #800000;"> </span><span style="color: #800000;">'</span><span style="color: #000000;">).Length </span><span style="color: #000000;">&gt;</span><span style="color: #000000;"> </span><span style="color: #800080;">1</span><span style="color: #000000;">)
            {
                temp </span><span style="color: #000000;">=</span><span style="color: #000000;"> line.Split(</span><span style="color: #800000;">'</span><span style="color: #800000;"> </span><span style="color: #800000;">'</span><span style="color: #000000;">);
                httpHeader.Add(temp[</span><span style="color: #800080;">0</span><span style="color: #000000;">], temp[</span><span style="color: #800080;">1</span><span style="color: #000000;">]);
                </span><span style="color: #0000FF;">return</span><span style="color: #000000;">;
            }
        }

        </span><span style="color: #0000FF;">#endregion</span><span style="color: #000000;">

        </span><span style="color: #0000FF;">#region</span><span style="color: #000000;"> IDisposable 鎴愬憳</span><span style="color: #000000;">

        </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> Dispose()
        {
            httpHeader.Clear();
            Conn </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">;
        }
        </span><span style="color: #0000FF;">#endregion</span><span style="color: #000000;">
    }
}</span></pre><!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --></div>

<p></p>

<p></p>

<p>运行后，打开IE，输入 <a href="http://localhost:8888">http://localhost:8888</a>，得到结果如下：</p>

<p><a href="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/edashttpServerhttp_13F87/image_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/Alexander-Lee/WindowsLiveWriter/edashttpServerhttp_13F87/image_thumb.png" width="325" height="94" /></a></p><img src="http://www.cnblogs.com/Alexander-Lee/aggbug/1601391.html?type=1" width="1" height="1" alt=""/><p>评论: 11　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/11/1601391.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/Alexander-Lee/archive/2009/11/11/1601391.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56855/" target="_blank">NDepend 3.0已与Visual Studio集成</a><span style="color:gray">(2010-02-10 16:17)</span><br/>· <a href="http://news.cnblogs.com/n/56854/" target="_blank">Ruby in Steel 1.5发布，去除IronRuby支持</a><span style="color:gray">(2010-02-10 16:14)</span><br/>· <a href="http://news.cnblogs.com/n/56852/" target="_blank">淘宝网通过索引模式涉足网络文学</a><span style="color:gray">(2010-02-10 15:59)</span><br/>· <a href="http://news.cnblogs.com/n/56851/" target="_blank">苹果发布 iPhone/iPad SDK 3.2 beta2 开发包</a><span style="color:gray">(2010-02-10 15:37)</span><br/>· <a href="http://news.cnblogs.com/n/56850/" target="_blank">“谷姐”：披着“谷歌”羊皮的悲哀？</a><span style="color:gray">(2010-02-10 15:32)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/news/tag/Buzz/" target="_blank">Google Buzz相关新闻</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item></channel></rss>