﻿<?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>IT博客-KiMoGiGi 技术文集-随笔分类-C# / Winforms</title><link>http://www.cnitblog.com/seeyeah/category/3169.html</link><description>不在乎选择什么，而在乎坚持多久……</description><language>zh-cn</language><lastBuildDate>Mon, 26 Sep 2011 10:57:11 GMT</lastBuildDate><pubDate>Mon, 26 Sep 2011 10:57:11 GMT</pubDate><ttl>60</ttl><item><title>格式化输出xml</title><link>http://www.cnitblog.com/seeyeah/archive/2011/03/16/73108.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 16 Mar 2011 03:49:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2011/03/16/73108.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/73108.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2011/03/16/73108.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/73108.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/73108.html</trackback:ping><description><![CDATA[<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;FormatXmlString<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;newline&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;tab&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;FormatXmlString()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">(Environment.NewLine,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\t</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;FormatXmlString(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;newline,&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;tab)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.newline&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;newline;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.tab&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;tab;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;FormatString(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;xmlString,&nbsp;Encoding&nbsp;encoding)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XmlDocument&nbsp;document&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;XmlDocument();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.LoadXml(xmlString);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder&nbsp;formatString&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;StringBuilder();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XmlWriterSettings&nbsp;setting&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;XmlWriterSettings();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setting.CheckCharacters&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setting.Encoding&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;encoding;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setting.Indent&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setting.IndentChars&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.tab.ToString();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setting.NewLineChars&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.newline;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;(XmlWriter&nbsp;writer&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;XmlWriter.Create(formatString,&nbsp;setting))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;document.WriteTo(writer);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;formatString.ToString();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyClass<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Test()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;rawXml&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">@"</span><span style="COLOR: #000000">&lt;?xml&nbsp;version=""1.0""&nbsp;encoding=""UTF-8""&nbsp;?&gt;&lt;root&gt;&lt;head&gt;&lt;serviceName&gt;aaaa&lt;/serviceName&gt;&lt;v&gt;1.0&lt;/v&gt;&lt;/head&gt;&lt;body&gt;&lt;clientId&gt;10&lt;/clientId&gt;&lt;clientIdExt&gt;1701&lt;/clientIdExt&gt;<br>&lt;clientIp&gt;192.168.1.1&lt;/clientIp&gt;&lt;timeToken&gt;20110315103732140&lt;/timeToken&gt;&lt;serviceId&gt;000&lt;/serviceId&gt;&lt;loginType&gt;1&lt;/loginType&gt;<br>&lt;loginName&gt;testtest&lt;/loginName&gt;&lt;loginPassword&gt;111111&lt;/loginPassword&gt;&lt;/body&gt;&lt;/root&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">FormatXmlString&nbsp;fxs&nbsp;=&nbsp;new&nbsp;FormatXmlString();</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FormatXmlString&nbsp;fxs&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;FormatXmlString(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;br&nbsp;/&gt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;format&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;fxs.FormatString(rawXml,&nbsp;Encoding.UTF8);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(format);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/73108.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2011-03-16 11:49 <a href="http://www.cnitblog.com/seeyeah/archive/2011/03/16/73108.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>文章摘选【20091008】</title><link>http://www.cnitblog.com/seeyeah/archive/2009/10/08/61734.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 08 Oct 2009 14:03:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2009/10/08/61734.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/61734.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2009/10/08/61734.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/61734.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/61734.html</trackback:ping><description><![CDATA[1、<a target="_blank"  href="http://www.codeproject.com/KB/toolbars/VS_IDE_Dock_Container.aspx">Visual Studio IDE like Dock Container - Second Version</a><br><br>仿VS IDE风格DockContainer插件，有标签预览功能，比较Cool的Ctrl+Tab预览。<br><br>2、<a target="_blank"  href="http://www.codeproject.com/KB/recipes/HashFile.aspx">Save Key/Value Pairs in a File</a><br><br>Hashtable运用方面非常广泛，但如果遇到大数据的话，会导致耗用大量内存。因此本文提供把Hashtable的数据结构存到&#8220;文件&#8221;的方案。<br><br>3、<a target="_blank"  href="http://www.codeproject.com/KB/aspnet/SandBox_CometSample.aspx">Using IHttpAsyncHandler and XMLHttpRequest to &#8220;push&#8221; messages to the client<br></a><br>一个从服务器&#8220;推&#8221;信息到客户端的方案。<br><br><br><img src ="http://www.cnitblog.com/seeyeah/aggbug/61734.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2009-10-08 22:03 <a href="http://www.cnitblog.com/seeyeah/archive/2009/10/08/61734.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>翻译 Threading in C#    </title><link>http://www.cnitblog.com/seeyeah/archive/2009/09/25/61560.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 24 Sep 2009 16:30:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2009/09/25/61560.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/61560.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2009/09/25/61560.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/61560.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/61560.html</trackback:ping><description><![CDATA[英文原版：<a style="text-decoration: underline;" target="_blank"  href="http://www.cnitblog.com/seeyeah/archive/2009/03/20/55575.html">http://www.cnitblog.com/seeyeah/archive/2009/03/20/55575.html</a><br>
<br>中文翻译：<a target="_blank"  href="http://knowledge.swanky.wu.googlepages.com/threading_in_c_sharp.html"><span style="text-decoration: underline;">http://knowledge.swanky.wu.googlepages.com/threading_in_c_sharp.html
</span></a><br> <img src ="http://www.cnitblog.com/seeyeah/aggbug/61560.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2009-09-25 00:30 <a href="http://www.cnitblog.com/seeyeah/archive/2009/09/25/61560.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原】扩展log4net的PatternLayout</title><link>http://www.cnitblog.com/seeyeah/archive/2009/09/20/61491.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sat, 19 Sep 2009 16:53:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2009/09/20/61491.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/61491.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2009/09/20/61491.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/61491.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/61491.html</trackback:ping><description><![CDATA[		<strong>
一、需求
</strong>
<br>
<br>PatternLayout的配置格式化如下所示：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">layout&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="log4net.Layout.PatternLayout"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">conversionPattern&nbsp;</span><span style="color: #ff0000;">value</span><span style="color: #0000ff;">="[%date{yyyy-MM-dd&nbsp;HH:mm:ss}]&nbsp;[%level]&nbsp;%message&nbsp;%exception&nbsp;%newline"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">layout</span><span style="color: #0000ff;">&gt;</span></div>
<br>由PatternLayout的conversionPattern来设置一个&#8220;模板&#8221;信息。其变量都有&#8220;%&#8221;开头的单词标识。如%level、%message；变量也可以传入参数，如%date{ yyyy-MM-dd HH:mm:ss }，其中yyyy-MM-dd HH:mm:ss就是%date的参数。<br><br>PatternLayout默认所可以支持的单词标识，请参考：<br><a style="text-decoration: underline;" target="_blank" href="http://www.cnitblog.com/seeyeah/archive/2008/10/15/50291.html">http://www.cnitblog.com/seeyeah/archive/2008/10/15/50291.html</a><br><br>现在我们需要扩展这些单词标记。<br>假设模板字符串定义如下所示：<br>&nbsp;[%date{yyyy-MM-dd HH:mm:ss}] %o{Message}，%o{User} %newline"<br>注意%o{Message}，%o是我们要实现扩展的一个标记，标识传入的message的对象，后面的参数{Message}、{User}表示message的对象的2个属性名。<br><br>我们先设计一个传递日志消息的实体类，定义如下所示<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;SampleMessage<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;Message&nbsp;{&nbsp;</span><span style="color: #0000ff;">get</span><span style="color: #000000;">;&nbsp;</span><span style="color: #0000ff;">set</span><span style="color: #000000;">;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;User&nbsp;{&nbsp;</span><span style="color: #0000ff;">get</span><span style="color: #000000;">;&nbsp;</span><span style="color: #0000ff;">set</span><span style="color: #000000;">;&nbsp;}<br>}</span></div>
<br><br>如下调用ILog的Info方法。<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">log.Info(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SampleMessage()&nbsp;{&nbsp;Message&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">Test1</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;User&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">User1</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;});<br>log.Info(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SampleMessage()&nbsp;{&nbsp;Message&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">Test2</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;User&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">User2</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;});</span></div>
<br><br>我们想要的结果如下所示：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">[</span><span style="color: #000000;">2009</span><span style="color: #000000;">-</span><span style="color: #000000;">09</span><span style="color: #000000;">-</span><span style="color: #000000;">19</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">14</span><span style="color: #000000;">:</span><span style="color: #000000;">27</span><span style="color: #000000;">:</span><span style="color: #000000;">29</span><span style="color: #000000;">]&nbsp;Test1，User1<br>[</span><span style="color: #000000;">2009</span><span style="color: #000000;">-</span><span style="color: #000000;">09</span><span style="color: #000000;">-</span><span style="color: #000000;">19</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">14</span><span style="color: #000000;">:</span><span style="color: #000000;">27</span><span style="color: #000000;">:</span><span style="color: #000000;">29</span><span style="color: #000000;">]&nbsp;Test2，User2&nbsp;</span></div>
<br><br><strong>二、方案<br></strong><br>Log4net用appender来记录日志的加载方式，内置就有很多种appender：RollingFileAppender、ConsoleAppender、AdoNetAppender等等。其中，日志信息的格式由appender中的layout掌控，log4net内置的layout是log4net.Layout.PatternLayout。<br><br>Appender（具体以RollingFileAppender为例，其他类型Appender类似）与layout的关系如下所示：<br>&nbsp;<br><img alt="" src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/log4net/1.jpg" height="464" width="396"><br><br>RollingFileAppender的基类FileAppender以及TextWriterAppender是文件日志类的公用基类。AppenderSkeleton是所有log4net的appender的基类，内部封装了常用方法，如线程锁定、日志等级过滤和支持一般的文件写入等。<br><br>另外一边的PatternLayout，结构跟Appender相似，IAppender包含一个ILayout负责格式化日志的格式。因此如果我们要扩展日志的格式化，就需要扩展PatternLayout。<br><strong><br></strong><strong>三、实现</strong><br><strong><br></strong>下面说明，扩展PatternLayout的实现过程。<br><br><strong>Step1：实现一个Converter</strong><br><br>Log4net内置提供的每个模板参数，都有对应的Converter做处理。如%message对应MessagePatternConverter；%date对应DatePatternConverter等。这个对应关系可以查看log4net的源代码PatternLayout.cs的静态构造函数，内部用一个静态的Hashtable管理关键字与Converter的关系：<strong><br></strong><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;Initialize&nbsp;the&nbsp;global&nbsp;registry<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;/summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;remarks&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;para&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;Defines&nbsp;the&nbsp;builtin&nbsp;global&nbsp;rules.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;/para&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;/remarks&gt;</span><span style="color: #808080;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;PatternLayout()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s_globalRulesRegistry&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Hashtable(</span><span style="color: #000000;">45</span><span style="color: #000000;">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s_globalRulesRegistry.Add(</span><span style="color: #000000;">"</span><span style="color: #000000;">literal</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(log4net.Util.PatternStringConverters.LiteralPatternConverter));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s_globalRulesRegistry.Add(</span><span style="color: #000000;">"</span><span style="color: #000000;">newline</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(log4net.Util.PatternStringConverters.NewLinePatternConverter));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s_globalRulesRegistry.Add(</span><span style="color: #000000;">"</span><span style="color: #000000;">n</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(log4net.Util.PatternStringConverters.NewLinePatternConverter));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s_globalRulesRegistry.Add(</span><span style="color: #000000;">"</span><span style="color: #000000;">c</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(LoggerPatternConverter));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s_globalRulesRegistry.Add(</span><span style="color: #000000;">"</span><span style="color: #000000;">logger</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(LoggerPatternConverter));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s_globalRulesRegistry.Add(</span><span style="color: #000000;">"</span><span style="color: #000000;">C</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(TypeNamePatternConverter));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s_globalRulesRegistry.Add(</span><span style="color: #000000;">"</span><span style="color: #000000;">class</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(TypeNamePatternConverter));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s_globalRulesRegistry.Add(</span><span style="color: #000000;">"</span><span style="color: #000000;">type</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(TypeNamePatternConverter));</span></div>
<strong><br></strong>再看看我们将要实现的模板字符串：<br>[%date{yyyy-MM-dd HH:mm:ss}] %o{Message}，%o{User} %newline"<br>我们要实现的关键字是&#8220;o&#8221;，按照log4net的PatternLayout的设计，我们也要相应实现一个Converter去解析关键字是&#8220;o&#8221;的内容，我们定义这个类名为ObjectConverter。<br><br>下面是ObjectConverter的实现方式，实现较为简单，详细看注释：<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;根据键值获取值的对象<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;/summary&gt;</span><span style="color: #808080;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">interface</span><span style="color: #000000;">&nbsp;IGetObjectValueByKey<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;GetByKey(</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;name);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;对应%o的对象转换器<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;/summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;remarks&gt;</span><span style="color: #008000;">用于PatternLayout</span><span style="color: #808080;">&lt;/remarks&gt;</span><span style="color: #808080;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ObjectConverter&nbsp;:&nbsp;PatternLayoutConverter<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;Func</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;funcs;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;ObjectConverter()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">********根据键值获取值的顺序<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">从接口获取值</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;funcs&nbsp;</span><span style="color: #000000;">+=</span><span style="color: #000000;">&nbsp;GetValueByInterface;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">反射获取属性值</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;funcs&nbsp;</span><span style="color: #000000;">+=</span><span style="color: #000000;">&nbsp;GetValueByReflection;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">从索引值获取值</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;funcs&nbsp;</span><span style="color: #000000;">+=</span><span style="color: #000000;">&nbsp;GetValueByIndexer;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;实现PatternLayoutConverter.Convert抽象方法<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;/summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;param&nbsp;name="writer"&gt;&lt;/param&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;param&nbsp;name="loggingEvent"&gt;&lt;/param&gt;</span><span style="color: #808080;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">override</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;Convert(TextWriter&nbsp;writer,&nbsp;LoggingEvent&nbsp;loggingEvent)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">获取传入的消息对象</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;objMsg&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;loggingEvent.MessageObject;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(objMsg&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">如果对象为空输出log4net默认的null字符串</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writer.Write(SystemInfo.NullText);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(</span><span style="color: #0000ff;">string</span><span style="color: #000000;">.IsNullOrEmpty(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.Option))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">如果属性为空，输出消息对象的ToString()</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writer.Write(objMsg.ToString());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;val&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;GetValue(funcs,&nbsp;objMsg,&nbsp;Option);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writer.Write(val&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">""</span><span style="color: #000000;">&nbsp;:&nbsp;val.ToString());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">#region</span><span style="color: #000000;">&nbsp;静态方法</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;循环方法列表，根据键值获取值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;/summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;param&nbsp;name="func"&gt;</span><span style="color: #008000;">方法列表委托</span><span style="color: #808080;">&lt;/param&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;param&nbsp;name="obj"&gt;</span><span style="color: #008000;">对象</span><span style="color: #808080;">&lt;/param&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;param&nbsp;name="name"&gt;</span><span style="color: #008000;">键值</span><span style="color: #808080;">&lt;/param&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;returns&gt;&lt;/returns&gt;</span><span style="color: #808080;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;GetValue(Func</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;func,&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;obj,&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;name)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;val&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(func&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">foreach</span><span style="color: #000000;">&nbsp;(Func</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;del&nbsp;</span><span style="color: #0000ff;">in</span><span style="color: #000000;">&nbsp;func.GetInvocationList())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;del(obj,&nbsp;name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">如果获取的值不为null，则跳出循环</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(val&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;val;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;使用接口方式取值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;/summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;param&nbsp;name="obj"&gt;&lt;/param&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;param&nbsp;name="name"&gt;&lt;/param&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;returns&gt;&lt;/returns&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;remarks&gt;</span><span style="color: #008000;">效率最高，避免了反射带来的效能损耗</span><span style="color: #808080;">&lt;/remarks&gt;</span><span style="color: #808080;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;GetValueByInterface(</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;obj,&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;name)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;val&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IGetObjectValueByKey&nbsp;objConverter&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;obj&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;IGetObjectValueByKey;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(objConverter&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;objConverter.GetByKey(name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;val;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;反射对象的获取属性，获取属性值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;/summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;param&nbsp;name="obj"&gt;&lt;/param&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;param&nbsp;name="name"&gt;&lt;/param&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;returns&gt;&lt;/returns&gt;</span><span style="color: #808080;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;GetValueByReflection(</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;obj,&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;name)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;val&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type&nbsp;t&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;obj.GetType();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;propertyInfo&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;t.GetProperty(name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(propertyInfo&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;propertyInfo.GetValue(obj,&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;val;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;反射对象的索引器，获取值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;/summary&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;param&nbsp;name="obj"&gt;&lt;/param&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;param&nbsp;name="name"&gt;&lt;/param&gt;</span><span style="color: #008000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #808080;">///</span><span style="color: #008000;">&nbsp;</span><span style="color: #808080;">&lt;returns&gt;&lt;/returns&gt;</span><span style="color: #808080;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;GetValueByIndexer(</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;obj,&nbsp;</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;name)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">&nbsp;val&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MethodInfo&nbsp;getValueMethod&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;obj.GetType().GetMethod(</span><span style="color: #000000;">"</span><span style="color: #000000;">get_Item</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(getValueMethod&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;getValueMethod.Invoke(obj,&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">object</span><span style="color: #000000;">[]&nbsp;{&nbsp;name&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;val;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">#endregion</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span></div>
<br><br><br>主要是ObjectConvertert按顺序用了3种从键值获取值的方式<br>1、&nbsp;&nbsp;&nbsp; 对象实现了我们所定义的接口IGetObjectValueByKey，直接调用方法获取。此方法效率最好，因为内部避免了反射所带来的损耗。<br>2、&nbsp;&nbsp;&nbsp; 用反射获取属性值<br>3、&nbsp;&nbsp;&nbsp; 用反射获取索引值<strong><br><br><br>Step2：把Converter注册到PatternLayout</strong><br><br>现在我们需要把已实现的ObjectConverter加入PatternLayout的解析逻辑中。<br>我们先从ILog中找到藏在里面的PatternLayout实例，实现如下代码所示：<strong><br><br></strong>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">var&nbsp;log&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Log4NetCommon.GetLog(</span><span style="color: #000000;">"</span><span style="color: #000000;">LogConfig1st</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>var&nbsp;appender&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;log.Logger.Repository.GetAppenders()[</span><span style="color: #000000;">0</span><span style="color: #000000;">];<br>var&nbsp;layout&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;((appender&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;AppenderSkeleton).Layout&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;PatternLayout);<br></span></div>
<strong><br></strong>Log4NetCommon是我们自己用于初始化Log4Net的工具类。log是我们一般主打使用日志的ILog实例，第二行我们找到对应的Appender，最后通过转换类型找到了PatternLayout。<br><br>PatternLayout提供了AddConverter方法，可以轻松加入我们刚实现Converter。<br>AddConverter有2个签名版本：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;AddConverter(ConverterInfo&nbsp;converterInfo)<br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;AddConverter(</span><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;name,&nbsp;Type&nbsp;type)</span></div>
<br>根据源代码对AddConverter的解析<br>Programmatic users should use the alternative &lt;see cref="AddConverter(string,Type)"/&gt; method.<br>我们还是按要求调用AddConverter(string name, Type type)的版本。<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">layout.AddConverter(</span><span style="color: #000000;">"</span><span style="color: #000000;">o</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(ObjectConverter));</span></div>
<br><br>但目前还是不能解析模板中关键字&#8220;o&#8221;，为什么呢？<br><br>首先我们先简单了解一下PatternLayout如何、在什么时候注册关键字与Converter。<br><br>1、&nbsp;&nbsp;&nbsp; 在PatternLayout中，定义了一个s_globalRulesRegistry的静态Hashtable，Key为关键字，Value为对应的Converter类型。在PatternLayout的静态构造函数中，先会注册log4net内置的45个关键字。<br>2、&nbsp;&nbsp;&nbsp; 初始化log4net配置的时候，会调用PatternLayout的ActivateOptions初始化以上的配置，以及在ActivateOptions中会调用CreatePatternParser解析配置中的模板字符串。<br><br>在初始化log4net配置的时候，都还没来得及AddConverter，log4net就已经解析完毕了。因此在调用了AddConverter，即修改了所有有关PatternLayout配置时，必须再手动调用一次ActivateOptions重新解析一次模板字符串。<br><br>全部代码实现如下所示：<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">var&nbsp;log&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Log4NetCommon.GetLog(</span><span style="color: #000000;">"</span><span style="color: #000000;">LogConfig1st</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br><br>var&nbsp;appender&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;log.Logger.Repository.GetAppenders()[</span><span style="color: #000000;">0</span><span style="color: #000000;">];<br>var&nbsp;layout&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;((appender&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;AppenderSkeleton).Layout&nbsp;</span><span style="color: #0000ff;">as</span><span style="color: #000000;">&nbsp;PatternLayout);<br>layout.AddConverter(</span><span style="color: #000000;">"</span><span style="color: #000000;">o</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #0000ff;">typeof</span><span style="color: #000000;">(ObjectConverter));<br>layout.ActivateOptions();<br></span></div>
<br>实现完毕！<br><br><strong><br></strong><strong>三、全部代码下载</strong><br><br><a href="http://www.cnitblog.com/Files/seeyeah/Log4NetPatternLayoutExtension.zip" title="Log4NetPatternLayoutExtension.zip">Log4NetPatternLayoutExtension.zip</a><br><br>  <img src ="http://www.cnitblog.com/seeyeah/aggbug/61491.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2009-09-20 00:53 <a href="http://www.cnitblog.com/seeyeah/archive/2009/09/20/61491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个简单的性能计数器：CodeTimer</title><link>http://www.cnitblog.com/seeyeah/archive/2009/09/17/61456.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 17 Sep 2009 05:19:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2009/09/17/61456.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/61456.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2009/09/17/61456.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/61456.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/61456.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 摘至：http://www.cnblogs.com/JeffreyZhao/archive/2009/03/10/CodeTimer.html有数据，有真相，相信大家在平时的工作或学习过程中，都需要比较几种不同方法或实现之间的性能差距。在这些时候，往往就需要我们不断地创建Stopwatch，打开，关闭，然后打印时间。这种一遍又一遍的重复终有一天会让人忍无可忍，因此如果能有一个“标准”的性能计数...&nbsp;&nbsp;<a href='http://www.cnitblog.com/seeyeah/archive/2009/09/17/61456.html'>阅读全文</a><img src ="http://www.cnitblog.com/seeyeah/aggbug/61456.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2009-09-17 13:19 <a href="http://www.cnitblog.com/seeyeah/archive/2009/09/17/61456.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Fast Reflection Library</title><link>http://www.cnitblog.com/seeyeah/archive/2009/09/17/61455.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 17 Sep 2009 05:16:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2009/09/17/61455.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/61455.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2009/09/17/61455.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/61455.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/61455.html</trackback:ping><description><![CDATA[摘至：http://www.cnblogs.com/JeffreyZhao/archive/2009/02/01/Fast-Reflection-Library.html<br /><br />这是我在CodePlex上创建的一个项目，它的网址是<a href="http://www.codeplex.com/FastReflectionLib">http://www.codeplex.com/FastReflectionLib</a>，使用Microsoft Public License (Ms-PL)，您可以随意在自己的产品中使用它的全部或部分代码。这个项目用到了我在《<a href="http://www.cnblogs.com/JeffreyZhao/archive/2008/11/24/invoke-method-by-lambda-expression.html">方法的直接调用，反射调用与Lambda表达式调用</a>》和《<a href="http://www.cnblogs.com/JeffreyZhao/archive/2009/01/09/DynamicPropertyAccessor-and-FastEval.html">这下没理由嫌Eval的性能差了吧？</a>》两篇文章里用到的做法，并加以提炼和扩展发布的项目——随便搞搞，留个印记，也供以后参考。 <h4>基本使用方式</h4><p>　
　反射是.NET中非常重要的功能。使用反射来构造对象、调用方法或是访问属性是某些项目中常用的做法之一（例如ORM框架）。众所周知，与一个成员的直
接访问相比，反射调用的性能要低好几个数量级。FastReflectionLib提供了一种简便的方式，使一些常用反射调用的性能得到大幅提高。如下：</p><pre class="code"><span style="color: blue;">using </span>System;<br /><span style="color: blue;">using </span>System.Reflection;<br /><span style="color: blue;">using </span>FastReflectionLib;<br /><br /><span style="color: blue;">namespace </span>SimpleConsole<br />{<br /><span style="color: blue;">class </span><span style="color: rgb(43, 145, 175);">Program<br /></span>{<br /><span style="color: blue;">static void </span>Main(<span style="color: blue;">string</span>[] args)<br />        {<br /><span style="color: rgb(43, 145, 175);">PropertyInfo </span>propertyInfo = <span style="color: blue;">typeof</span>(<span style="color: blue;">string</span>).GetProperty(<span style="color: rgb(163, 21, 21);">"Length"</span>);<br /><span style="color: rgb(43, 145, 175);">MethodInfo </span>methodInfo = <span style="color: blue;">typeof</span>(<span style="color: blue;">string</span>).GetMethod(<span style="color: rgb(163, 21, 21);">"Contains"</span>);<br /><br /><span style="color: blue;">string </span>s = <span style="color: rgb(163, 21, 21);">"Hello World!"</span>;<br /><br /><span style="color: green;">// get value by normal reflection<br /></span><span style="color: blue;">int </span>length1 = (<span style="color: blue;">int</span>)propertyInfo.GetValue(s, <span style="color: blue;">null</span>);<br /><span style="color: green;">// get value by the extension method from FastReflectionLib,<br />            // which is much faster<br /></span><span style="color: blue;">int </span>length2 = (<span style="color: blue;">int</span>)propertyInfo.FastGetValue(s);<br /><br /><span style="color: green;">// invoke by normal reflection<br /></span><span style="color: blue;">bool </span>result1 = (<span style="color: blue;">bool</span>)methodInfo.Invoke(s, <span style="color: blue;">new object</span>[] { <span style="color: rgb(163, 21, 21);">"Hello" </span>});<br /><span style="color: green;">// invoke by the extension method from FastReflectionLib,<br />            // which is much faster<br /></span><span style="color: blue;">bool </span>result2 = (<span style="color: blue;">bool</span>)methodInfo.FastInvoke(s, <span style="color: blue;">new object</span>[] { <span style="color: rgb(163, 21, 21);">"Hello" </span>});<br />        }<br />    }<br />}<br /></pre><p>　　在得到了PropertyInfo或MethodInfo对象之后，我们可以使用GetValue或Invoke方法来访问属性或调用方法。在
FastReflectionLib中为PropertyInfo、MethodInfo等对象定义了对应的扩展方法，于是我们就可以使用这些扩展方法
（从代码上看来，基本上只是在原来的方法之前加上“Fast”）来进行调用，与之前的方法相比，新的扩展方法性能有极大的提高。</p><h4>直接使用各工作对象</h4><p>　　各FastXxx方法实际上是将PropertyInfo等对象作为Key去一个Cache中获取对应的工作对象，然后调用工作对象上对应的方法。因此，直接调用工作对象可以获得更好的性能。各工作对象类型的对应关系如下：</p><ul><li>PropertyInfo：IPropertyAccessor 
</li><li>MethodInfo：IMethodInvoker 
</li><li>ConstructorInfo：IConstructorInvoker 
</li><li>FieldInfo：IFieldAccessor</li></ul><p>　　我们可以使用FastReflectionCaches.MethodInvokerCache来获取一个IMethodInvoker对象：</p><pre class="code"><span style="color: blue;">static void </span>Execute(<span style="color: rgb(43, 145, 175);">MethodInfo </span>methodInfo, <span style="color: blue;">object </span>instance, <span style="color: blue;">int </span>times)<br />{ <br /><span style="color: rgb(43, 145, 175);">IMethodInvoker </span>invoker = <span style="color: rgb(43, 145, 175);">FastReflectionCaches</span>.MethodInvokerCache.Get(methodInfo);<br /><span style="color: blue;">object</span>[] parameters = <span style="color: blue;">new object</span>[0];<br /><span style="color: blue;">for </span>(<span style="color: blue;">int </span>i = 0; i &lt; times; i++)<br />    {<br />        invoker.Invoke(instance, parameters);<br />    }<br />}<br /></pre><h4>工作对象的默认实现与扩展</h4><p>　　在FastReflectionLib中，已经提供了IPropertyAccessor等接口的默认实现。该实现将会构造一颗表达式树
（Expression
Tree）并将其编译（调用其Compile方法）以获得一个与反射方法签名相同的委托对象。这是一种简单、通用而安全的实现，由于Compile方法使
用了Emit，其性能也较为令人满意（可见下面的性能测试）。但是这并不是性能最高的做法，如果使用Emit生成最优化的代码，其性能甚至会高于方法的直
接调用（例如<a href="http://www.codeplex.com/Dynamic">Dynamic Reflection Library</a>）。如果您想使用更好的实现来替换，则可以自行构造一个工作对象接口的实现，并替换对应的Factory：</p><pre class="code"><span style="color: blue;">public class </span><span style="color: rgb(43, 145, 175);">BetterPropertyAccessor </span>: <span style="color: rgb(43, 145, 175);">IPropertyAccessor<br /></span>{<br /><span style="color: blue;">public </span>BetterPropertyAccessor(<span style="color: rgb(43, 145, 175);">PropertyInfo </span>propertyInfo) { ... }<br /><br />    ...<br />}<br /><br /><span style="color: blue;">public class </span><span style="color: rgb(43, 145, 175);">BetterPropertyAccessorFactory </span>:<br /><span style="color: rgb(43, 145, 175);">IFastReflectionFactory</span>&lt;<span style="color: rgb(43, 145, 175);">PropertyInfo</span>, <span style="color: rgb(43, 145, 175);">IPropertyAccessor</span>&gt;<br />{<br /><span style="color: blue;">public </span><span style="color: rgb(43, 145, 175);">IPropertyAccessor </span>Create(<span style="color: rgb(43, 145, 175);">PropertyInfo </span>key)<br />    {<br /><span style="color: blue;">return new </span><span style="color: rgb(43, 145, 175);">BetterPropertyAccessor</span>(key);<br />    }<br />}<br /><br /><span style="color: blue;">class </span><span style="color: rgb(43, 145, 175);">Program<br /></span>{<br /><span style="color: blue;">static void </span>Main(<span style="color: blue;">string</span>[] args)<br />    {<br /><span style="color: rgb(43, 145, 175);">FastReflectionFactories</span>.PropertyAccessorFactory =<br /><span style="color: blue;">new </span><span style="color: rgb(43, 145, 175);">BetterPropertyAccessorFactory</span>();<br /><br />        ...<br />    }<br />}<br /></pre><h4>缓存的默认实现与扩展</h4><p>　　在FastReflectionLib中使用基于
System.Collections.Generic.Dictionary&lt;TKey,
TValue&gt;类型编写的缓存容器。每次调用FastXxx扩展方法时，类库将从对应的缓存容器中获取工作对象。如果缓存容器中还没有所需的工作对
象，那么它就会调用合适的Factory来构造新的工作对象。从下面的性能测试来看，许多时间是消耗在缓存查找上的，如果您有更好的缓存实现，可以使用以
下的方法替换默认的缓存的容器：</p><pre class="code"><span style="color: blue;">public class </span><span style="color: rgb(43, 145, 175);">BetterMethodInvokerCache </span>:<br /><span style="color: rgb(43, 145, 175);">IFastReflectionCache</span>&lt;<span style="color: rgb(43, 145, 175);">MethodInfo</span>, <span style="color: rgb(43, 145, 175);">IMethodInvoker</span>&gt;<br />{<br /><span style="color: blue;">public </span><span style="color: rgb(43, 145, 175);">IMethodInvoker </span>Get(<span style="color: rgb(43, 145, 175);">MethodInfo </span>key) { ... }<br />}<br /><br /><span style="color: blue;">class </span><span style="color: rgb(43, 145, 175);">Program<br /></span>{<br /><span style="color: blue;">static void </span>Main(<span style="color: blue;">string</span>[] args)<br />    {<br /><span style="color: rgb(43, 145, 175);">FastReflectionCaches</span>.MethodInvokerCache = <br /><span style="color: blue;">new </span><span style="color: rgb(43, 145, 175);">BetterMethodInvokerCache</span>();<br /><br />        ...<br />    }<br />}<br /></pre><h4>根据需要自行缓存工作对象</h4><p>　　FastReflectionLib中通过PropertyInfo等对象作为Key，对PropertyAccessor等工作对象进行缓
存。但是在某些场景下，您也可以选择合适的方式来自行缓存工作对象。与FastReflectionLib源码同时发布的CustomCache示例网站
中包含了一个FastEval扩展，在某些场景下，我们可以使用这个更高效的方法来替换内置的Eval方法。这个示例的特点如下：</p><ul><li>使用对象的类型和属性名同时作为缓存的Key获取对应的PropertyAccessor对象 
</li><li>使用PropertyAccessor获取“匿名对象”中的属性值 
</li><li>缓存的作用域为特定页面，而不是整个AppDomain。</li></ul><h4>性能测试</h4><p>　　FastReflectionLib源码中包含了一个性能测试项目，您可以从中看出FastReflectionLib对于反射的性能改进。摘录部分数据如下（测试在我的笔记本上运行，Release编译）。</p><p>　　执行以下方法：</p><pre class="code"><span style="color: blue;">public class </span><span style="color: rgb(43, 145, 175);">Test<br /></span>{<br /><span style="color: blue;">public void </span>MethodWithArgs(<span style="color: blue;">int </span>a1, <span style="color: blue;">string </span>a2) { }<br />}<br /></pre><p>　　进行一百万次调用，结果如下：</p><table border="1" cellpadding="5" cellspacing="0"><tbody align="middle"><tr><td><strong>调用方式</strong></td><td><strong>消耗时间（秒）</strong></td></tr><tr><td>方法直接调用</td><td>0.0071397</td></tr><tr><td>内置反射调用</td><td>1.4936181</td></tr><tr><td>工作对象调用</td><td>0.0468326</td></tr><tr><td>Fast方法调用</td><td>0.1373712</td></tr></tbody></table><br /><img src ="http://www.cnitblog.com/seeyeah/aggbug/61455.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2009-09-17 13:16 <a href="http://www.cnitblog.com/seeyeah/archive/2009/09/17/61455.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在C#中生成指定长度的随机字符</title><link>http://www.cnitblog.com/seeyeah/archive/2009/05/12/57119.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 12 May 2009 02:30:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2009/05/12/57119.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/57119.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2009/05/12/57119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/57119.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/57119.html</trackback:ping><description><![CDATA[
		<p>摘至：http://www.cnblogs.com/nclly/archive/2008/12/19/1357961.html<br /></p>
		<p>
				<br />
		</p>
		<p>///&lt;summary&gt;<br />
///得到随机字符.<br />
///&lt;/summary&gt;<br />
///&lt;param name="intLength"&gt;Length of the int.&lt;/param&gt;<br />
///&lt;param name="booNumber"&gt;if set to &lt;c&gt;true&lt;/c&gt; [boo number].&lt;/param&gt;<br />
///&lt;param name="booSign"&gt;if set to &lt;c&gt;true&lt;/c&gt; [boo sign].&lt;/param&gt;<br />
///&lt;param name="booSmallword"&gt;if set to &lt;c&gt;true&lt;/c&gt; [boo smallword].&lt;/param&gt;<br />
///&lt;param name="booBigword"&gt;if set to &lt;c&gt;true&lt;/c&gt; [boo bigword].&lt;/param&gt;<br />
///&lt;returns&gt;&lt;/returns&gt;<br />
public string getRandomizer(int intLength, bool booNumber, bool booSign, bool booSmallword, bool booBigword)<br />
{<br />
 //定义<br />
 Random ranA = new Random();<br />
 int intResultRound = 0;<br />
 int intA = 0;<br />
 string strB = "";<br />
 while (intResultRound &lt; intLength)<br />
 {<br />
  //生成随机数A，表示生成类型<br />
  //1=数字，2=符号，3=小写字母，4=大写字母<br />
  intA = ranA.Next(1, 5);<br />
  //如果随机数A=1，则运行生成数字<br />
  //生成随机数A，范围在0-10<br />
  //把随机数A，转成字符<br />
  //生成完，位数+1，字符串累加，结束本次循环<br />
  if (intA == 1 &amp;&amp; booNumber)<br />
  {<br />
   intA = ranA.Next(0, 10);<br />
   strB = intA.ToString() + strB;<br />
   intResultRound = intResultRound + 1;<br />
   continue;<br />
  }<br />
  //如果随机数A=2，则运行生成符号<br />
  //生成随机数A，表示生成值域<br />
  //1：33-47值域，2：58-64值域，3：91-96值域，4：123-126值域<br />
  if (intA == 2 &amp;&amp; booSign == true)<br />
  {<br />
   intA = ranA.Next(1, 5);<br />
   //如果A=1<br />
   //生成随机数A，33-47的Ascii码<br />
   //把随机数A，转成字符<br />
   //生成完，位数+1，字符串累加，结束本次循环<br />
   if (intA == 1)<br />
   {<br />
    intA = ranA.Next(33, 48);<br />
    strB = ((char)intA).ToString() + strB;<br />
    intResultRound = intResultRound + 1;<br />
    continue;<br />
   }</p>
		<p>   //如果A=2<br />
   //生成随机数A，58-64的Ascii码<br />
   //把随机数A，转成字符<br />
   //生成完，位数+1，字符串累加，结束本次循环<br />
   if (intA == 2)<br />
   {<br />
    intA = ranA.Next(58, 65);<br />
    strB = ((char)intA).ToString() + strB;<br />
    intResultRound = intResultRound + 1;<br />
    continue;<br />
   }</p>
		<p>   //如果A=3<br />
   //生成随机数A，91-96的Ascii码<br />
   //把随机数A，转成字符<br />
   //生成完，位数+1，字符串累加，结束本次循环<br />
   if (intA == 3)<br />
   {<br />
    intA = ranA.Next(91, 97);<br />
    strB = ((char)intA).ToString() + strB;<br />
    intResultRound = intResultRound + 1;<br />
    continue;<br />
   }</p>
		<p>   //如果A=4<br />
   //生成随机数A，123-126的Ascii码<br />
   //把随机数A，转成字符<br />
   //生成完，位数+1，字符串累加，结束本次循环<br />
   if (intA == 4)<br />
   {<br />
    intA = ranA.Next(123, 127);<br />
    strB = ((char)intA).ToString() + strB;<br />
    intResultRound = intResultRound + 1;<br />
    continue;<br />
   }<br />
  }</p>
		<p>  //如果随机数A=3，则运行生成小写字母<br />
  //生成随机数A，范围在97-122<br />
  //把随机数A，转成字符<br />
  //生成完，位数+1，字符串累加，结束本次循环<br />
  if (intA == 3 &amp;&amp; booSmallword == true)<br />
  {<br />
   intA = ranA.Next(97, 123);<br />
   strB = ((char)intA).ToString() + strB;<br />
   intResultRound = intResultRound + 1;<br />
   continue;<br />
  }</p>
		<p>  //如果随机数A=4，则运行生成大写字母<br />
  //生成随机数A，范围在65-90<br />
  //把随机数A，转成字符<br />
  //生成完，位数+1，字符串累加，结束本次循环<br />
  if (intA == 4 &amp;&amp; booBigword == true)<br />
  {<br />
   intA = ranA.Next(65, 89);<br />
   strB = ((char)intA).ToString() + strB;<br />
   intResultRound = intResultRound + 1;<br />
   continue;<br />
  }<br />
 }<br />
 return strB;<br />
}</p>
		<p>//随机字符串生成器的主要功能如下： <br />
//1、支持自定义字符串长度<br />
//2、支持自定义是否包含数字<br />
//3、支持自定义是否包含小写字母<br />
//4、支持自定义是否包含大写字母<br />
//5、支持自定义是否包含特殊符号<br />
//6、支持自定义字符集</p>
		<p>///&lt;summary&gt;<br />
///生成随机字符串<br />
///&lt;/summary&gt;<br />
///&lt;param name="length"&gt;目标字符串的长度&lt;/param&gt;<br />
///&lt;param name="useNum"&gt;是否包含数字，1=包含，默认为包含&lt;/param&gt;<br />
///&lt;param name="useLow"&gt;是否包含小写字母，1=包含，默认为包含&lt;/param&gt;<br />
///&lt;param name="useUpp"&gt;是否包含大写字母，1=包含，默认为包含&lt;/param&gt;<br />
///&lt;param name="useSpe"&gt;是否包含特殊字符，1=包含，默认为不包含&lt;/param&gt;<br />
///&lt;param name="custom"&gt;要包含的自定义字符，直接输入要包含的字符列表&lt;/param&gt;<br />
///&lt;returns&gt;指定长度的随机字符串&lt;/returns&gt;<br />
public string GetRnd(int length, bool useNum, bool useLow, bool useUpp, bool useSpe, string custom)<br />
{<br />
 byte[] b = new byte[4];<br />
 new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(b);<br />
 Random r = new Random(BitConverter.ToInt32(b, 0));<br />
 string s = null, str = custom;<br />
 if (useNum == true) { str += "0123456789"; }<br />
 if (useLow == true) { str += "abcdefghijklmnopqrstuvwxyz"; }<br />
 if (useUpp == true) { str += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }<br />
 if (useSpe == true) { str += "!\"#$%&amp;'()*+,-./:;&lt;=&gt;?@[\\]^_`{|}~"; }<br />
 for (int i = 0; i &lt; length; i++)<br />
 {<br />
  s += str.Substring(r.Next(0, str.Length - 1), 1);<br />
 }<br />
 return s;<br />
}</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/57119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2009-05-12 10:30 <a href="http://www.cnitblog.com/seeyeah/archive/2009/05/12/57119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分享 Threading in C# - Free E-book</title><link>http://www.cnitblog.com/seeyeah/archive/2009/03/20/55575.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Fri, 20 Mar 2009 02:29:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2009/03/20/55575.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/55575.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2009/03/20/55575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/55575.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/55575.html</trackback:ping><description><![CDATA[
		<b>
				<u>
						<a target="_blank" href="http://www.albahari.com/threading/">Threading in C# </a>
				</u>
		</b>
		<br />
		<br />By <b>Joseph Albahari</b><br /><br /><b><u><a href="http://www.albahari.com/threading/threading.pdf">Download PDF</a></u></b><br /><img src ="http://www.cnitblog.com/seeyeah/aggbug/55575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2009-03-20 10:29 <a href="http://www.cnitblog.com/seeyeah/archive/2009/03/20/55575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>权限设计文摘</title><link>http://www.cnitblog.com/seeyeah/archive/2009/01/11/53705.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sun, 11 Jan 2009 13:11:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2009/01/11/53705.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/53705.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2009/01/11/53705.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/53705.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/53705.html</trackback:ping><description><![CDATA[<a class=headermaintitle id=Header1_HeaderTitle href="http://www.cnblogs.com/b4n73/"><u><font color=#0000ff>等长青</font></u></a><br>1、<a title=通用权限的设计(上) href="http://www.cnblogs.com/b4n73/archive/2009/01/09/1372404.html"><u><font color=#800080>通用权限的设计(上)</font></u></a><br>2、<a title=通用权限的设计(下) href="http://www.cnblogs.com/b4n73/archive/2009/01/09/1372807.html"><u><font color=#800080>通用权限的设计(下)</font></u></a><br>3、<a class=postTitle2 id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/b4n73/archive/2009/01/10/1373458.html"><u><font color=#800080>再说权限设计</font></u></a> <br><br><a class=headermaintitle id=Header1_HeaderTitle href="http://www.cnblogs.com/zhouqi/"><u><font color=#0000ff>lukcy</font></u></a><br>1、<a class=postTitle2 id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/zhouqi/archive/2008/01/22/1047966.html"><u><font color=#800080>权限设计</font></u></a> <br><br><a href="http://www.cnblogs.com/llxxbb/"><u><font color=#800080>李学斌</font></u></a> <br>1、<a class=postTitle2 id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/llxxbb/archive/2008/04/21/Platform_UserSystem.html"><u><font color=#800080>平台架构--用户系统</font></u></a> <br><br><a class=headermaintitle id=Header1_HeaderTitle href="http://www.cnblogs.com/yukaizhao/"><u><font color=#0000ff>赵玉开</font></u></a><br>1、<a class=postTitle2 id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/yukaizhao/archive/2007/04/15/user_role_action_permission.html"><u><font color=#800080>应用程序权限设计</font></u></a> <br><br><a href="http://www.cnblogs.com/jyk/"><u><font color=#0000ff>金色海洋（jyk）</font></u></a> <br>1、<a class=postTitle2 id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/jyk/archive/2008/04/29/1176050.html"><u><font color=#0000ff>通用权限的思路。只是一个简单的思路。</font></u></a> <br>2、<a class=postTitle2 id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/jyk/archive/2008/05/01/1178753.html"><u><font color=#800080>通用权限的思路。带有数据库关系图</font></u></a> <br><br><a href="http://www.cnblogs.com/tsoukw/"><u><font color=#0000ff>Kevin Zou</font></u></a><br>1、<a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/tsoukw/archive/2008/05/29/1210050.html"><u><font color=#800080>解耦的故事--权限设计</font></u></a> 
<img src ="http://www.cnitblog.com/seeyeah/aggbug/53705.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2009-01-11 21:11 <a href="http://www.cnitblog.com/seeyeah/archive/2009/01/11/53705.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原】使用MSFTPSRVR和PSFTP架设sftp方案简述。</title><link>http://www.cnitblog.com/seeyeah/archive/2008/12/29/53229.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 29 Dec 2008 13:51:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/12/29/53229.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/53229.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/12/29/53229.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/53229.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/53229.html</trackback:ping><description><![CDATA[<p><strong style="FONT-SIZE: 18pt">一、准备工作&nbsp;</strong></p>
<p><a name=_Toc217961024><strong><span><span>1、<span> </span></span></span></strong><strong><span>msftpsrvr.exe</span></strong></a><span><strong><span>（服务器端）</span></strong></span><strong></strong></p>
<p><span>由</span><span>coreftp</span><span>开发的迷你</span><span>sftp</span><span>服务软件，无需任何安装。</span></p>
<p><span>网址：</span><span><a href="http://www.coreftp.com/server/index.html">http://www.coreftp.com/server/index.html</a><br><br></span></p>
<p><a name=_Toc217961025><strong><span><span>2、<span> </span></span></span></strong><strong><span>psftp.exe</span></strong></a><span><strong><span>（客户端）</span></strong></span><strong></strong></p>
<p><span>PSFTP</span><span>是</span><span>PuTTY SFTP</span><span>客户端，用于本地与服务器间安全传输文件（使用</span><span>SSH</span><span>连接）。</span></p>
<p><span>网址：</span><span><a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html">http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html</a><br><br></span></p>
<p><span><span>3、&nbsp;</span></span><strong><span>创建</span><span>Window Service</span></strong><strong><span>（服务器端）</span></strong><span><br></span><span>使用</span><span>C#</span><span>语言、</span><span>Visual Studio </span><span>开发工具，创建</span><span>Window Service</span><span>，用于管理</span><span>msftpsrvr.exe</span><span>在服务器的启动状况。</span><span><br></span><span>以服务开启</span><span>msftpsrvr.exe</span><span>进程，可以实现系统启动时启动、避免登录用户注销导致进程关闭。</span></p>
<p><br><strong style="FONT-SIZE: 18pt">二、具体创建</strong></p>
<p>&nbsp;</p>
<p><a name=_Toc217961027><strong><span>1</span></strong></a><span><strong><span>、服务器配置</span><span>msftpsrvr.exe</span></strong></span><strong></strong></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span>msftpsrvr.exe</span><span>的界面如下所示：</span></p>
<p><img src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/screenshot.jpg" border=0>&nbsp;<br></p>
<p><span>其中</span><span>Root</span><span>为</span><span>sftp</span><span>存储文件设置根目录文件夹，点击</span><span>Start</span><span>後程式就会侦听客户端的链接。</span><span>Connections</span><span>的列表可以查看当前客户端正在连接的状态。</span><span>Port</span><span>推荐为</span><span>22</span><span>，其他端口的话会可能被防火墙挡住。</span></p>
<p>&nbsp;</p>
<p><span>填写的所有信息（即</span><span>User, Password, Port, Root</span><span>）会以当前登录用户，贮存在注册表中。因此由不同用户登录操作系统的话，此</span><span>sftp</span><span>的信息都会分别存储。</span></p>
<p>&nbsp;</p>
<p><span>现在的目标是用</span><span>Window Service</span><span>（服务）启动此程序，出现</span><strong><span>2</span></strong><strong><span>个问题</span></strong><span>：</span></p>
<p><span><span>1)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>启动服务是以</span><span>System</span><span>用户启动，因此进程</span><span>msftpsrvr.exe</span><span>归属于</span><span>System</span><span>用户，进程打开后是没有任何</span><span>UI</span><span>显示的。因此</span><span>sftp</span><span>所需要的信息（即</span><span>User, Password, Port, Root</span><span>）就无法设置。</span></p>
<p><span><span>2)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>启动进程，但还需要点击&#8220;</span><span>Start</span><span>&#8221;的按钮。在没有</span><span>UI</span><span>的情况怎么令</span><span>msftpsrvr.exe</span><span>自动进入</span><span>Start</span><span>状态。</span></p>
<p>&nbsp;</p>
<p><strong><span>解决方案</span></strong><span>：</span></p>
<p><span><span>1)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>msftpsrvr.exe</span><span>保存的信息都在注册表中，如果是当前登录用户，储存的路径就是</span><span>HKEY_CURRENT_USER\Software\FTPWare</span><span>。</span><span><br></span><span>如下图所示：</span></p>
<p><img height=335 src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/SFTP/1.JPG" width=615 border=0><br></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>类似的，可以在注册表的用户默认设置，添加</span><span>sftp</span><span>的信息。路径为</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HKEY_USERS\.DEFAULT\Software\FTPWare</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>在这里模仿添加上图中的</span><span>Path</span><span>、</span><span>Port</span><span>、</span><span>PW</span><span>、</span><span>User</span><span>的数值。</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>这样，以其他任何用户初始打开</span><span>sftp</span><span>的时候，都会有我们所设置的默认值，当然包括启动服务的</span><span>System</span><span>用户。</span></p>
<p>&nbsp;</p>
<p><span><span>2)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>启动</span><span>msftpsrvr.exe</span><span>时，添加</span><span> &#8211;start </span><span>命令参数即可。</span></p>
<p>&nbsp;</p>
<p><a name=_Toc217961028><strong><span>2</span></strong></a><span><strong><span>、使用</span><span>psftp.exe</span></strong></span><strong></strong></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>点击打开</span><span>psftp.exe</span><span>，出现如下图的命令窗口。</span></p>
<p>&#160;</p>
<p>&nbsp;<img height=171 src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/SFTP/2.JPG" width=569 border=0></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>输入</span><span>open [user]@[host]</span><span>，</span><span>user</span><span>为用户名，</span><span>host</span><span>为</span><span>sftp</span><span>服务器的</span><span>ip</span><span>，如输入</span></p>
<p>&nbsp;</p>
<p><span>open aaa@172.18.235.56</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span>回车后出现以下提示</span></p>
<p>&#160;</p>
<p>&nbsp;<img height=248 src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/SFTP/3.JPG" width=602 border=0></p>
<p><span>输入</span><span>n</span><span>，不需要把</span><span>key</span><span>缓存；然后提示输入密码。成功连接后，就会返回命令符。</span></p>
<p>&nbsp;</p>
<p><span>输入</span><span>put [FilePath] </span><span>就可以把文件传到</span><span>sftp</span><span>的文件夹中。如输入</span></p>
<p>&nbsp;</p>
<p><span>put &#8220;D:\temp\temp\sftp</span><span>架设方案</span><span>.doc&#8221;</span></p>
<p>&nbsp;</p>
<p><img height=404 src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/SFTP/4.JPG" width=613 border=0></p>
<p>&nbsp;</p>
<p><span>上传文件到</span><span>sftp</span><span>成功。</span></p>
<p>&nbsp;</p>
<p><span>以上是命令行操作</span><span>psftp</span><span>。如需要像批处理文件，直接执行任务。可利用</span><span>psftp</span><span>的命令参数。如下所示：</span></p>
<p>&nbsp;</p>
<p><span>"psftp.exe" aaa@127.0.0.1 -pw aaa -b "aaa.txt" -bc</span></p>
<p>&nbsp;</p>
<p><span>解释：</span></p>
<p><span><span>1)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>aaa@127.0.0.1</span><span>：要直接连接目标</span><span>sftp</span><span>服务器，</span><span>aaa</span><span>为用户名，</span><span>127.0.0.1</span><span>为服务器</span><span>ip</span><span>。</span></p>
<p><span><span>2)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>&#8211;pw aaa</span><span>：设置密码为</span><span>aaa</span><span>。</span></p>
<p><span><span>3)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>-b "aaa.txt" </span><span>：指定需要操作的命令文本。</span><span><br></span><span>具体</span><span>aaa.txt</span><span>的文本内容，如下所示：</span><span><br>put "FBMS</span><span>前台宣导材料再稿</span><span>.ppt"</span></p>
<p><span><span>4)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>&#8211;bc</span><span>：输出执行过的命令语句。</span></p>
<p>&nbsp;</p>
<p><span>这样的话，可以直接执行</span><span>"psftp.exe" aaa@127.0.0.1 -pw aaa -b "aaa.txt" &#8211;bc</span><span>可以顺利连接服务器并执行指定任务。</span></p>
<p>&nbsp;</p>
<p><span>C#</span><span>执行的时候就可以拼凑命令字符串，然后直接执行。</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span>Psftp</span><span>参数和命令参考</span></p>
<p>&nbsp;</p>
<p><span>Usage: psftp [options] [user@]host</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=91>
            <p align=center><strong><span>Options:</span></strong></p>
            </td>
            <td vAlign=top width=477>
            <p align=center><strong><span>描述</span></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-V </span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>print version information and exit</span><span>（打印版本）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-pgpfp</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>print PGP key fingerprints and exit</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-b file</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>use specified batchfile</span><span>（读取格式化文件，按照文件格式执行命令，及预先要交互的命令都放到这个文件里）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-bc</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>output batchfile commands </span><span>（输出执行过的命令语句）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-be</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>don't stop batchfile processing if errors</span><span>（遇错跳过）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-v</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>show verbose messages </span><span>（详细回显）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-load sessname</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>Load settings from saved session </span><span>（使用预先保存好的</span><span>sessname</span><span>，保存在</span><span>HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions</span><span>）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-l user</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>connect with specified username </span><span>（用户名）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-P port</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>connect to specified port </span><span>（端口）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-pw passw</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>login with specified password </span><span>（密码）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-1 -2</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>force use of particular SSH protocol version </span><span>（使用</span><span>ssh</span><span>协议）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-4 -6</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>force use of IPv4 or IPv6&nbsp;</span><span>（支持</span><span>ipv4 </span><span>或</span><span>ipv6</span><span>）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-C</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>enable compression </span><span>（支持压缩格式，节省带宽）</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-i key</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>private key file for authentication</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-noagent</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>disable use of Pageant</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-agent</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>enable use of Pageant</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>-batch</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>disable all interactive prompts </span><span>不允许交互命令</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span>psftp</span><span>命令：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=91>
            <p align=center><strong><span>命令</span></strong></p>
            </td>
            <td vAlign=top width=477>
            <p align=center><strong><span>描述</span></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>bye&nbsp;</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>结束</span><span> psftp </span><span>。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>cd<span>&nbsp;&nbsp; </span></span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>改变远程服务器的目录。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>chmod</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>改变远程服务器的文件或文件夹的权限及属性。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><st1:state w:st="on"><st1:place w:st="on"><span>del</span></st1:place></st1:state><span><span>&nbsp;&nbsp; </span></span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>删除远程服务器上的文件。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>dir<span>&nbsp;&nbsp; </span></span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>列出远程服务器上的所有文件和目录。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>exit&nbsp;</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>结束</span><span> psftp </span><span>。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>get<span>&nbsp;&nbsp; </span></span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>从远程服务器上下载指定文件。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>help&nbsp;</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>使用帮助。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>lcd<span>&nbsp;&nbsp; </span></span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>改变本地计算机的工作目录。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>lpwd </span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>显示本地计算机工作目录。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>ls<span>&nbsp;&nbsp;&nbsp; </span></span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>列出远程服务器上的所有文件和目录。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>mkdir</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>在远程服务器上建立一个目录。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>mv&nbsp;</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>移动远程服务器上的文件或者改名。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>open </span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>连接指定的远程服务器。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>put&nbsp;</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>把本地的文件上传到远程服务器上。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>pwd&nbsp;</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>移动远程服务器上的文件或者改名。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>quit</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>结束</span><span> psftp </span><span>。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>reget&nbsp;</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>断点下载未完的指定文件。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>ren&nbsp;</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>移动远程服务器上的文件或者改名。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>reput </span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>断点上传未完的指定文件。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>rm&nbsp;</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>刪除远程服务器上的一个文件。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=91>
            <p><span>rmdir</span></p>
            </td>
            <td vAlign=top width=477>
            <p><span>刪除远程服务器上的一个目录。</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><a name=_Toc217961029><strong><span>3</span></strong></a><span><strong><span>、开发</span><span>window service</span></strong></span><strong></strong></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Window Service</span><span>的作用在于</span><span>Window Service</span><span>可以以</span><span>System</span><span>的用户启动进程，</span><span>System</span><span>用户是不会注销的，因此其他登录用户注销时，可以避免以服务开启的进程关闭。</span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Visual Studio</span><span>开发</span><span>Window</span><span>服务，先新建&#8220;</span><span>Windows </span><span>服务&#8221;项目。</span></p>
<p>&nbsp;</p>
<p><img height=404 alt="" src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/SFTP/5.JPG" width=613 border=0></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>在</span><span>Service1.cs</span><span>中编写服务启动代码：</span></p>
<p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span></p>
<p align=left><span><span>&nbsp;&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;partial&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Service1&nbsp;:&nbsp;ServiceBase<br><br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Service1()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeComponent();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">override</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnStart(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">[]&nbsp;args)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StartSftpServer();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">override</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnStop()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;StartSftpServer()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(Process.GetProcessesByName(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">msftpsrvr.exe</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">).Length&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Process&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Process();<br><br>&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProcessStartInfo&nbsp;startInfo&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ProcessStartInfo();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startInfo.Arguments&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">-start</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startInfo.FileName&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">@"</span><span style="COLOR: #000000">d:&nbsp;\msftpsrvr.exe</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.StartInfo&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;startInfo;<br><br>&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.Start();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;}<br></span></div>
<p align=left></span></span></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>显示</span><span>Services1</span><span>的设计界面，点击右键选择&#8220;添加安装程序&#8221;。在项目就会自动生成</span><span>ProjectInstaller.cs</span><span>。用于配置</span><span>Window</span><span>服务的基本信息。</span></p>
<p>&nbsp;<img height=373 src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/SFTP/6.JPG" width=487 border=0></p>
<p align=center></p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>注意选择</span><span>serviceProcessInstaller</span><span>的时候，</span><span>Accout</span><span>要需要选择</span><span>LocalSystem</span><span>，这样服务才会以</span><span>System</span><span>用户启动。</span></p>
<p align=center></p>
<p>&nbsp;<img height=217 src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/SFTP/7.JPG" width=521 border=0></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>编译后，需要用</span><span>.net framework</span><span>的命令符把服务注册到操作系统中。如下选择</span><span>Visual Studio </span><span>命令提示。</span></p>
<p>&#160;</p>
<p>&nbsp;<img height=147 src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/SFTP/8.JPG" width=586 border=0></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>在命令行输入如下指令，即可成功把服务应用程序安装到操作系统。</span></p>
<p><span>InstallUtil "D:\temp\WindowsService1\bin\Debug\WindowsService1.exe"</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;<img height=153 src="http://www.cnitblog.com/images/cnitblog_com/seeyeah/SFTP/9.JPG" width=584 border=0>&nbsp;&nbsp; </span></span></p>
<p><br>&nbsp; </p>
<p><span style="FONT-SIZE: 18pt"><strong>三</strong></span><a name=_Toc217961030><span style="FONT-SIZE: 18pt"><strong>、&nbsp;其他改进</strong></span></a></p>
<p>&nbsp;</p>
<p><span><span>1、&nbsp;</span></span><span>msftpsrvr.exe</span><span>的注册表设置可以到处一个</span><span>reg</span><span>文件，方便导入注册表。</span></p>
<p><span><span>2、&nbsp;</span></span><span>Window Service</span><span>可以设置一个定时器，每隔一段时间查看进程是否在启动中，如果没有则开启。</span></p>
<p><span><span>3、&nbsp;</span></span><span>Window Service</span><span>提供输入参数的设置，可以灵活配置</span><span>Window Service</span><span>所要启动的应用程序。</span></p>
<p><br></p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/53229.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-12-29 21:51 <a href="http://www.cnitblog.com/seeyeah/archive/2008/12/29/53229.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>提升windows forms应用速度的几个简单方法</title><link>http://www.cnitblog.com/seeyeah/archive/2008/12/23/52963.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 23 Dec 2008 09:01:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/12/23/52963.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/52963.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/12/23/52963.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/52963.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/52963.html</trackback:ping><description><![CDATA[摘至：http://www.cnblogs.com/jjx/archive/2007/08/06/844585.html<br>
<br>整理中,欢迎大家补充<br><br>一 ngen /gac<br>将assembly放到gac中,并用ngen 预先编译, 应用程序装入会成n倍的提升<br><br>虽然ngen 有一大堆缺点,但windows forms应用,启动速度很重要,在实践中,我建议如下使用ngen<br><br>1. 只对不常变的 assembly进行ngen ,通常,这都是第三方的dll ,比方说第三方的ui控件,像devexpress或是janus的组件<br>2. 明确assembly之间的依赖, 这有助于你简短正确的写出ngen install 命令<br>比方说 devexpress.xtragrid依赖devexpress.xtraeditors,devexpres.data,devexpress.utils,而ngen会自动分析依赖关系,所以你只需要写一句 <br>ngen install devexpress.xtragrid.v7.2.dll 即可<br><br>3. 为了不影响clickonce 进行应用程序分发,可以考虑将这些dll另做一个包,让用户单独安装,通常可以使用批处理文件来完成<br><br>gacutils&nbsp; /i xxx.dll<br>ngen install xxx.dll<br><br>同时提供反删除脚本<br><br>二 控制assembly /method 大小,并且按需引用<br>分层的设计思想有助于达成这点, 这样能降低jit 的负担,比方说你可以将项目分成一下子项目<br>myapp.service.interface<br>myapp.service.impl<br>myapp.models<br>myapp.views<br>myapp.launce<br><br>如果存在多个子系统, 最好分离成多个assembly项目,并且将公共的项目抽取为类似 myapp.views.comm 之类的项目<br><br>任何时候都不要放弃重构, 漂亮的实现通常也会有漂亮的性能<br><br>这条同时也提醒你,在views操作中不要有 业务逻辑,业务逻辑通常可以在引用models层(如果你使用domain model driven 开发),或是引用service.interface (如果你使用transaction script模式)<br><br>三 设计插件结构<br>插件结构能够达成仅在需要时才将相应的组件调入内存,通常,要达成如上目标,需要将插件描述和插件本身分离<br>简单的,可以借助于spring.net ioc 的object lazy init功能<br>&lt;objects default-lazy-init="true"&nbsp; ...<br>来达到仅在需要时才会创建新实例<br><br>四&nbsp;进行垃圾收集<br>内存的大小对应用程序影响很大,windows forms通常会在窗口最小化时自动收集,我们也可以学习 idea 的方法,在工具栏或状态栏上放一个垃圾收集按钮,并通过颜色,数字提示用户内存的占用情况<br><br>在编码上,要知道gc不是万能的,除了注意正确使用dispose外,还要在一些可能会导致gc问题的地方多多使用WeakReference<br><br>五&nbsp;按需装载ui<br>使用tab控件将ui分组,在相应的tabpage激活时才进行相应的装载和访问行为<br><br>通
常,windows forms的form都会比较复杂, 比方说一个报价单窗体可能会最近报价单列表,报价单和明细编辑,还盘分析,报价参数设定,
每个假定是1秒时间(包含数据库访问)的话,全部装入就要5秒,但通常,form装入时只有一个page是激活的,这种方式可以form装入减少到1秒<br><br>六 使用按钮,在需要时才调入相应的form<br>这条的意思时,有时你要对表单中的数据作一些操作,而且可能需要输入一些(比较少的额外数据,或是做些选择),通常,你会在这个form中加入这些控件. 这条的意思是将这些控件分离到一个独立的form, 仅当用户点击相应按钮时才调入form.<br>分离操作总是有好处的(当然,你要掌握分离的度)<br><br>btw: 五/六 两点的想法来自于microsoft dynamics 4.0的ui构造<br><br>七 尽量控制使用第三方 assmebly <br>通
常,内置的组件,比方说 System.Windows.Forms.dll
都是已经预先编译完成的,通常可以达到较好的启动速度,同时,这些内置的组件逻辑和ui渲染比较简单 , 执行速度也相对不错 .
引入第三方组件越多,jit 负担就越重. 系统要花较多时间在assembly的装载和方法编译上.<br><br>八 检查事件的重复触发<br>通
常,有些事件会重复发生多次,有时,这些事件发生可能违反你的想法,比方说
bindingsource.RemoveCurrent后会触发bindingsource.ListChanged事件,而且type是
ItemChanged, 如果这些时候有耗时操作,通常会对速度有明显影响<br><br>九 养成使用BeginUpdate和EndUpdate 的良好习惯<br>这条最简单,但也最会容易忽视.通常,beginUpdate和endupdate会大大提高 ui的渲染速度,大家可以简单的测试treeview装载节点时使用BeginUpdate和EndUpdate和不使用之间的速度差别,肯定会让你吃惊.<br><br>十 当发现性能有问题时,使用dottrace 分析具体原因,避免盲目的优化<br>通常盲目的优化是要不得的,比方说现在常见的exception 性能的讨论.&nbsp;&nbsp; 我个人强烈推荐jetbrains 的dottrace 3.0 .<br><br>十一 如果发现有好的做法,请一定要提升为基础实现, 通常的做法是提取基类 ,或是提取公共函数,以达到重用目的
<br><img src ="http://www.cnitblog.com/seeyeah/aggbug/52963.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-12-23 17:01 <a href="http://www.cnitblog.com/seeyeah/archive/2008/12/23/52963.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>to NGen or not to NGen, that is the question</title><link>http://www.cnitblog.com/seeyeah/archive/2008/12/23/52962.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 23 Dec 2008 09:00:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/12/23/52962.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/52962.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/12/23/52962.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/52962.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/52962.html</trackback:ping><description><![CDATA[<strong> <font color="#0079a2"><br><a href="http://www.blogcn.com/user8/flier_lu/index.html?id=1550010&amp;run=.04005F8">http://www.blogcn.com/user8/flier_lu/index.html?id=1550010&amp;run=.04005F8</a><br><br></font></strong> &nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.wintellect.com/about/instructors/instructorbios.aspx?id=3" target="_blank">Jeffrey&nbsp;Richter</a>曾在<a href="http://www.codeguru.com/" target="_blank">CodeGuru</a>上发表过一篇讨论是否应该使用NGen的文章。(ngen.exe支持将CLR格式的IL代码编译成Native的代码，避免载入时再次JIT编译)
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.codeguru.com/Csharp/.NET/net_general/toolsand3rdparty/print.php/c4651/" target="_blank">JIT&nbsp;Compilation&nbsp;and&nbsp;Performance&nbsp;-&nbsp;To&nbsp;NGen&nbsp;or&nbsp;Not&nbsp;to&nbsp;NGen?</a></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;文中的观点是应该在大多数程序中避免使用ngen预编译IL代码为Native代码，因为JIT编译器可能比ngen更了解用户的系统。例如JIT编译器有以下优势：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.可以知道用户正在使用的什么类型的CPU，是PII、PIII还是P4，并编译生成相应的优化指令<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.可以知道用户当前是使用单CPU还是多CPU，以便优化线程锁定机制<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.可以避免ngen静态编译带来的DLL载入时重定位问题等等</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;而且使用ngen预编译代码还会带来一些潜在的问题：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.没有知识产权保护：与某些人预期的不同，ngen生成的Native代码不能独立发布。因为其中没有包含Metadata信息，所以还是必须与原始的IL代码一同发布<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.ngen生成的文件可能不同步：CLR在载入ngen生成的文件时，要检测其编译时的属性是否与当前环境匹配，不匹配则使用缺省的JIT编译<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.难以管理：ngen生成的文件不能自动删除，因此违背了.NET架构程序的XCOPY分发策略<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.低劣的载入时性能(重定位)：如果ngen生成的DLL文件的基址已经被占用，则载入时需要重定位(rebase)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.低劣的运行时性能：ngen生成的文件采用较为保守的假定环境，因此代码效率低于JIT编译<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6.
某些应用程序域(domain)的载入策略会忽略ngen生成的文件：assembly可以以应用程序域相关(non-domain-neutral)和
无关(domain-neutral)的方式被载入，但ngen生成的文件假设只有mscorlib.dll以应用程序域无关的方式被载入。因此当某个
assembly通过应用程序域无关的方式被使用，则ngen生成的代码无法使用，还是要通过JIT编译。例如ASP.NET中所有具有
strongly-named的assembly都会被通过应用程序域无关的方式载入。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因此Jeffrey&nbsp;Richter认为，只有对于客户端程序能够有可测量的载入性能提升的情况下，才应该使用ngen预编译代码，而对于其他程序，特别是服务器端程序，都应该避免ngen的使用。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不过CLR组的<a href="http://blogs.msdn.com/junfeng/" target="_blank">Junfeng&nbsp;Zhang</a>并不十分赞同上述观点，故而在其BLog上发表了一篇批驳的文章<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://blogs.msdn.com/junfeng/archive/2004/03/27/97304.aspx" target="_blank">JIT&nbsp;Compilation&nbsp;and&nbsp;Performance&nbsp;-&nbsp;To&nbsp;NGen&nbsp;or&nbsp;Not&nbsp;to&nbsp;NGen?&nbsp;</a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;文中对Jeffrey&nbsp;Richter提出的ngen的几个潜在问题逐条反驳：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.ngen并不是用来保护知识产权的工具，只是优化载入时性能而已，可以通过其他工具如混淆器(obfuscator)保护知识产权<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.一般只有在维护.NET&nbsp;Framework和自己的程序后，才会导致不同步问题，而此时可以使用ngen重新生成预编译文件<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.ngen支持&nbsp;/delete&nbsp;命令行参数，因此可以通过写一个批处理文件完成自动删除<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.重定位是所有dll都存在的问题，并不能为了避免重定位就不使用dll而采用巨大的exe文件，因此这不能作为不使用ngen的理由。而且CLR载入dll的时候会检测这种情况的发生，并在合适的情况下拒绝使用ngen生成的文件<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.CLR
目前的JIT编译器对所有代码只编译一次，而不是象Sun的Hotspot那样，监视已JIT的代码，根据动态行为重新JIT优化性能。而ngen具有的
JIT无法达到的优势是可以跨assembly做一些代码的优化。不过ngen代码还是比JIT编译平均有5%-10%的性能损失，单能大大提高载入速
度。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6.ngen编译的文件的确在某些情况下无法被使用，但这并不能作为不使用ngen的理由<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;此外ngen还有个优点是其生成的代码可以被多个进程共享，而JIT编译生成的代码在私有地址空间中。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因此ngen在客户端代码的处理上还是有价值的，呵呵<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;后面MS的<a href="http://blogs.msdn.com/joshwil/" target="_blank">Josh&nbsp;Williams</a>又补充说，在64位版本的.NET中，ngen生成代码的性能可能比JIT代码有较大改善，因为ngen包含了一些对JIT来说过于复杂的全局优化措施。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;最后<a href="http://blogs.msdn.com/junfeng/" target="_blank">Junfeng&nbsp;Zhang</a>还给出了一个性能优化的指导性文章的链接<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://msdn.microsoft.com/visualc/default.aspx?pull=/library/en-us/dv_vstechart/html/profileguidedoptimization.asp" target="_blank">Profile-Guided&nbsp;Optimization&nbsp;with&nbsp;Microsoft&nbsp;Visual&nbsp;C++&nbsp;2005</a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;有趣的讨论，通过这种BLog的论战，很容易就能够获得一些通过正规渠道文章无法了解的内幕消息，呵呵</p>
<br><img src ="http://www.cnitblog.com/seeyeah/aggbug/52962.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-12-23 17:00 <a href="http://www.cnitblog.com/seeyeah/archive/2008/12/23/52962.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[STAThread]的含义</title><link>http://www.cnitblog.com/seeyeah/archive/2008/12/22/52881.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 22 Dec 2008 01:43:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/12/22/52881.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/52881.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/12/22/52881.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/52881.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/52881.html</trackback:ping><description><![CDATA[摘至：http://www.cnblogs.com/huashanlin/archive/2007/07/07/809305.html
<br><hr style="width: 100%; height: 2px;"><span style="font-weight: bold;"></span><br>
<p>[STAThread]<br>STAThread：Single&nbsp;&nbsp;&nbsp;&nbsp; Thread&nbsp;&nbsp;&nbsp;&nbsp; Apartment Thread.(单一线程单元线程)<br>[]是用来表示Attributes；<br><br>[STAThread]<br>是一种线程模型，用在程序的入口方法上（在C#和VB.NET里是Main()方法），来指定当前线程的ApartmentState 是STA。用在其他方法上不产生影响。在aspx页面上可以使用<strong> AspCompat = "true"</strong>
来达到同样的效果。这个属性只在&nbsp; Com&nbsp; Interop&nbsp; 有用，如果全部是&nbsp; managed&nbsp; code&nbsp;
则无用。简单的说法:[STAThread]指示应用程序的默认线程模型是单线程单元
(STA)。启动线程模型可设置为单线程单元或多线程单元。如果未对其进行设置，则该线程不被初始化。也就是说如果你用的.NET
Framework，并且没有使用COM Interop，一般不需要这个Attribute。其它的还有MTA（多线程套间）、Free&nbsp;
Thread（自由线程）。 <br><br>[STAThread] attribute指示应用程序的 COM 线程模型是单线程单元。<br>而于此对应的多线程单元则是 [MTAThread] （多线程单元线程）<br><br>COM 线程模型只适用于使用 COM interop 的应用程序。如果将此属性应用到不使用 COM interop 的应用程序，将没有任何效果。</p>
<p>COM 线程模型可设置为单线程单元或多线程单元。如果应用程序线程实际调用了 COM 组件，则仅为 COM interop 初始化该线程。如果没有使用 COM interop，则不初始化该线程。<br><br>以下是找到的一个资料介绍：<br><strong> Q.
When I create a c# project from scratch in VS.NET, the generated code
always have a [STAThread] attribute above the main routine. What does
the STAThread attribute really do? Can I change it to MTAThread
instead? I have searched website and books, no one seems to explain
this well.</strong>  </p>
<p><em> Asked by anon. Answered by the Wonk on February 17, 2003</em>  </p>
<p style="margin-right: 0px;"><strong> A.</strong>  </p>
<p>The STAThreadAttribute marks a thread to use the Single-Threaded COM
Apartment if COM is needed. By default, .NET won't initialize COM at
all. It's only when COM is needed, like when a COM object or COM
Control is created or when drag 'n' drop is needed, that COM is
initialized. When that happens, .NET calls the underlying
CoInitializeEx function, which takes a flag indicating whether to join
the thread to a multi-threaded or single-threaded apartment.</p>
<p>A multi-threaded apartment (MTA) in COM is more efficient, since any
of a number of RPC threads from a pool can be used to handle a request.
However, an object on the MTA thread needs to protect itself from
multiple threads accessing it at the same time, so that efficiency
comes at a cost.</p>
<p>The single-thread apartment (STA) in COM is inherently
single-threaded and therefore no additional thread synchronization is
needed. The STA is implemented using the thread's Windows message
queue, which is how requests to objects on an STA are serialized.
Because of how the STA thread is implemented, calls to objects on that
thread are serialized with Windows message handling on that thread,
making sure that everything, both the COM objects and the underlying
windowing objects, e.g. HWNDs, are all synchronized. This is necessary
for UI-oriented COM objects, like controls and drag 'n' drop, which
must also be synchronized together with the UI.</p>
When COM is needed .NET will call CoInitializeEx, picking the MTA by
default because it's more efficient. However, to get the
synchronization needed for controls, windows and drag 'n' drop, you
need to mark a thread's entry point with the STAThreadAttribute to let
.NET know to initialize the UI thread on the STA. All of the VS.NET
project templates put that attribute in to make sure you don't forget:<br>大致意思是：由于很多COM在.NET环境下如果使用多线程的话，会导致引用的COM不能正常运行，而如果不声明程序为STAThread的话，.NET就会自动使用多线程来提高效率，这样就会导致不可预知的后果。<br><br><br><br><br>以下引用另一同辈的发言：<a href="http://blog.csdn.net/qilang/archive/2006/06/06/775605.aspx">http://blog.csdn.net/qilang/archive/2006/06/06/775605.aspx</a><br><strong> STA不是单线程的意思.英文为single&nbsp;threaded&nbsp;apartment.是一种套间(或译为公寓)线程模式.<br><br></strong> <font size="2">sta&nbsp;thread并不表明应用程式的类型,和应用程序不搭界,恰相反,一个应用程序可以有多个线程.每个线程也可以有多个组件或对象.以前win16位系统的组件线程模式才真正是单线程.这是一种被淘汰了的模式.<br>线程模式用于处理组件在多线程的环境里并行与并互的方式.比如套间线程(STAThread)模式中接口跨线程传递必须被调度(Marshal),不调度直传肯定会失败!而MTA或FreeThread模式中的接口可以不经调度直接传递.<br>这种调度在特定的环境中非常影响性能(可有几百倍之差).如VB里只支持STAThread模式.FreeThread模式的组件会在里面表现成和跨进程一样慢!<br>线程模式是微软的COM基础中的极其重要的概念.一定要吃透!<br>我对.net真是一窍不通(没空去弄,对不起微软去年的奖赏).但我可以肯定,C#中的[STAThread]属性是应用程序的套间初始化代码.可以直接理解成SDK里的<br>CoInitialize(NULL);&nbsp;<br>初始一个STA套间实际上是相当于开了一个消息窗口,所有调用经此窗口过程调度到组件内.<br>同理[MTAThread](不知有没有这个属性,自已去查)<br>可以理解成<br>CoInitializeEx(NULL,COINIT_MULTITHREADED&nbsp;)<br>这经常是一个对初入com大门的人来说,有一定难度但必须过的一道关.</font>
<br><img src ="http://www.cnitblog.com/seeyeah/aggbug/52881.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-12-22 09:43 <a href="http://www.cnitblog.com/seeyeah/archive/2008/12/22/52881.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>运行内网服务器上.Net程序权限的问题</title><link>http://www.cnitblog.com/seeyeah/archive/2008/12/11/52539.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 11 Dec 2008 07:48:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/12/11/52539.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/52539.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/12/11/52539.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/52539.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/52539.html</trackback:ping><description><![CDATA[摘至：http://blog.sina.com.cn/s/blog_593b4d5001000ben.html
<br><br><hr style="width: 100%; height: 2px;"><br>在.Net之前，如果在客户机上执行内网服务器共享目录中的一个EXE程序，尽管这个程序中有操作本地注册表和MUTEX的功能，执行起来也不会遇到什么阻碍。但是如果用.Net写这样一个EXE就会就些麻烦：对本机注册表和MUTEX的操作都失败了。<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 解决方法：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 找到和这个EXE相对应的.Net Framework版本的目录中的caspol.exe<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 假设这个EXE程序的目录是在：\\Svr1\public$\EXE\ShowNotice.exe<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 执行：caspol.exe -resolvegroup \\Svr1\public$\EXE\ShowNotice.exe<br>你将会看到这个程序所属的代码组。一般来说它属于：1.2. Zone-Intranet:LocalIntranet<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 执行：caspol.exe -chggroup 1.2 FullTrust<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样所有这个代码组的程序在本机上都能正常执行。当然前提是当前用户帐号对本机有足够的权限，比如，它本身是能够操作注册表的。 <br><br><img src ="http://www.cnitblog.com/seeyeah/aggbug/52539.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-12-11 15:48 <a href="http://www.cnitblog.com/seeyeah/archive/2008/12/11/52539.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#多线程学习(一) 多线程的相关概念</title><link>http://www.cnitblog.com/seeyeah/archive/2008/11/20/51701.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 20 Nov 2008 00:46:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/11/20/51701.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/51701.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/11/20/51701.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/51701.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/51701.html</trackback:ping><description><![CDATA[摘至：http://www.cnblogs.com/xugang/archive/2008/04/06/1138856.html
<br><hr style="width: 100%; height: 2px;"><strong>什么是进程？</strong><br>
<p><font face="Verdana">
</font><font face="Verdana">当一个程序开始运行时，它就是一个进程，进程包括运行中的程序和程序所使用到的内存和系统资源。<br>
而一个进程又是由多个线程所组成的。<br>
<br>
</font><font face="Verdana"><strong>什么是线程？</strong><br>
线程是程序中的一个执行流，每个线程都有自己的专有寄存器(栈指针、程序计数器等)，但代码区是共享的，即不同的线程可以执行同样的函数。<br>
<br>
<strong>什么是多线程？</strong><br>
多线程是指程序中包含多个执行流，即在一个程序中可以同时运行多个不同的线程来执行不同的任务，也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。<br>
<br>
<strong>多线程的好处：</strong><br>
可以提高CPU的利用率。在多线程程序中，一个线程必须等待的时候，CPU可以运行其它的线程而不是等待，这样就大大提高了程序的效率。 <br>
<br>
<strong>多线程的不利方面：</strong><br>
线程也是程序，所以线程需要占用内存，线程越多占用内存也越多； <br>
多线程需要协调和管理，所以需要CPU时间跟踪线程； <br>
线程之间对共享资源的访问会相互影响，必须解决竞用共享资源的问题；<br>
线程太多会导致控制太复杂，最终可能造成很多Bug；</font></p>
<p><font face="Verdana">接下来将对C#编程中的多线程机制进行探讨。为了省去创建GUI那些繁琐的步骤，更清晰地逼近线程的本质，接下来的所有程序都是控制台程序，程序最后的Console.ReadLine()是为了使程序中途停下来，以便看清楚执行过程中的输出。 <br>
<br>
<span style="color: red;">任何程序在执行时，至少有一个主线程。</span><br>
<br>
一个直观印象的线程示例：</font></p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #008000;"><font face="Verdana">//</font></span><span style="color: #008000;"><font face="Verdana">SystemThread.cs</font></span><span style="color: #008000;"><font face="Verdana"><br>
</font></span><span style="color: #0000ff;"><font face="Verdana">using</font></span><span style="color: #000000;"><font face="Verdana">&nbsp;System;<br>
</font></span><span style="color: #0000ff;"><font face="Verdana">using</font></span><span style="color: #000000;"><font face="Verdana">&nbsp;System.Threading;&nbsp;<br>
<br>
</font></span><span style="color: #0000ff;"><font face="Verdana">namespace</font></span><span style="color: #000000;"><font face="Verdana">&nbsp;ThreadTest<br>
{<br>
</font></span><span style="color: #0000ff;"><font face="Verdana">class</font></span><span style="color: #000000;"><font face="Verdana">&nbsp;RunIt<br>
{<br>
[STAThread]<br>
</font></span><span style="color: #0000ff;"><font face="Verdana">static</font></span><span style="color: #000000;"><font face="Verdana">&nbsp;</font></span><span style="color: #0000ff;"><font face="Verdana">void</font></span><span style="color: #000000;"><font face="Verdana">&nbsp;Main(</font></span><span style="color: #0000ff;"><font face="Verdana">string</font></span><span style="color: #000000;"><font face="Verdana">[]&nbsp;args)<br>
{<br>
Thread.CurrentThread.Name</font></span><span style="color: #000000;"><font face="Verdana">=</font></span><span style="color: #800000;"><font face="Verdana">"</font></span><span style="color: #800000;"><font face="Verdana">System&nbsp;Thread</font></span><span style="color: #800000;"><font face="Verdana">"</font></span><span style="color: #000000;"><font face="Verdana">;</font></span><span style="color: #008000;"><font face="Verdana">//</font></span><span style="color: #008000;"><font face="Verdana">给当前线程起名为"System&nbsp;Thread"</font></span><span style="color: #008000;"><font face="Verdana"><br>
</font></span><span style="color: #000000;"><font face="Verdana">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(Thread.CurrentThread.Name</font></span><span style="color: #000000;"><font face="Verdana">+</font></span><span style="color: #800000;"><font face="Verdana">"</font></span><span style="color: #800000;"><font face="Verdana">'Status:</font></span><span style="color: #800000;"><font face="Verdana">"</font></span><span style="color: #000000;"><font face="Verdana">+</font></span><span style="color: #000000;"><font face="Verdana">Thread.CurrentThread.ThreadState);<br>
Console.ReadLine();<br>
}<br>
}<br>
}</font></span></div>
<font face="Verdana"><br>
</font>
<p><font face="Verdana"><font face="Verdana">输出如下： <br>
System Thread's Status:Running <br>
<br>
</font><font face="Verdana">在这里，我们通过Thread类的静态属性CurrentThread获取了当前执行的线程，对其Name属性赋值&#8220;System Thread&#8221;，最后还输出了它的当前状态（ThreadState）。<br>
<br>
所谓<span style="color: red;">静态属性</span>，就是这个类所有对象所公有的属性，不管你创建了多少个这个类的实例，但是类的静态属性在内存中只有一个。很容易理解CurrentThread为什么是静态的——虽然有多个线程同时存在，但是在某一个时刻，CPU只能执行其中一个。 <br>
<br>
在程序的头部，我们使用了如下命名空间：<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;using System;<br>
&nbsp;&nbsp;&nbsp;&nbsp; using System.Threading;&nbsp;<br>
&nbsp;<br>
在.net framework class library中，所有与多线程机制应用相关的类都是放在System.Threading命名空间中的。如果你想在你的应用程序中使用多线程，就必须包含这个类。<br>
<br>
我们通过其中提供的Thread类来创建和控制线程，ThreadPool类用于管理线程池等。<br>
（此外还提供解决了线程执行安排，死锁，线程间通讯等实际问题的机制。）<br>
<br>
<span style="color: red;">Thread类有几个至关重要的方法，描述如下：<br>
</span>Start()：启动线程；<br>
Sleep(int)：静态方法，暂停当前线程指定的毫秒数； <br>
Abort()：通常使用该方法来终止一个线程；<br>
Suspend()：该方法并不终止未完成的线程，它仅仅挂起线程，以后还可恢复； <br>
Resume()：恢复被Suspend()方法挂起的线程的执行；<br>
<br>
</font></font></p>
<p><font face="Verdana"><font face="Verdana"><font face="Verdana"><strong style="color: red;"></strong>&nbsp;</font></font></font></p>
<p><font face="Verdana"><font face="Verdana"><font face="Verdana"><strong style="color: red;">C#多线程学习系列：</strong></font></font></font></p>
<p><font face="Verdana"><font face="Verdana"><font face="Verdana">C#多线程学习(二) 如何操纵一个线程<br>
<a  href="http://www.cnblogs.com/xugang/archive/2008/04/06/1138841.html">http://www.cnblogs.com/xugang/archive/2008/04/06/1138841.html</a></font></font></font></p>
<p><font face="Verdana"><font face="Verdana"><font face="Verdana">&nbsp;</font></font></font></p>
<p><font face="Verdana"><font face="Verdana"><font face="Verdana">C#多线程学习(三) 生产者和消费者<br>
<a  href="http://www.cnblogs.com/xugang/archive/2008/03/23/1118594.html">http://www.cnblogs.com/xugang/archive/2008/03/23/1118594.html</a></font></font></font></p>
<p><font face="Verdana"><font face="Verdana"><font face="Verdana">&nbsp;</font></font></font></p>
<p><font face="Verdana"><font face="Verdana"><font face="Verdana">C#多线程学习(四) 多线程的自动管理(线程池)<br>
<a  href="http://www.cnblogs.com/xugang/archive/2008/03/23/1118584.html">http://www.cnblogs.com/xugang/archive/2008/03/23/1118584.html</a></font></font></font></p>
<p><font face="Verdana"><font face="Verdana"><font face="Verdana">&nbsp;</font></font></font></p>
<p><font face="Verdana"><font face="Verdana"><font face="Verdana">C#多线程学习(五) 多线程的自动管理(定时器)<br>
<a  href="http://www.cnblogs.com/xugang/archive/2008/03/23/1118537.html">http://www.cnblogs.com/xugang/archive/2008/03/23/1118537.html</a></font></font></font></p>
<p><font face="Verdana"><font face="Verdana"><font face="Verdana">&nbsp;</font></font></font></p>
<p><font face="Verdana"><font face="Verdana"><font face="Verdana">C#多线程学习(六) 互斥对象<br>
<a  href="http://www.cnblogs.com/xugang/archive/2008/03/23/1118530.html">http://www.cnblogs.com/xugang/archive/2008/03/23/1118530.html</a></font></font></font></p><img src ="http://www.cnitblog.com/seeyeah/aggbug/51701.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-11-20 08:46 <a href="http://www.cnitblog.com/seeyeah/archive/2008/11/20/51701.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Threading in .NET and WinForms</title><link>http://www.cnitblog.com/seeyeah/archive/2008/11/11/51342.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 11 Nov 2008 13:55:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/11/11/51342.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/51342.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/11/11/51342.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/51342.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/51342.html</trackback:ping><description><![CDATA[摘至：<a href="http://www.codeproject.com/KB/threads/Threading.aspx">http://www.codeproject.com/KB/threads/Threading.aspx</a><br>
<hr>
<h2>Introduction</h2>
<p>This article is to guide you through creating and handling threads in .NET. It has two sections: in the first section, we will see about threading basics and how to create threads in .NET using C#. In the second section, we will see how to handle threads in WinForms.</p>
<h2>1.1 Threading</h2>
<h3>1.1.1 Threading Basics</h3>
<p>If you are familiar with threading basics, you can skip this topic.</p>
<p>A thread can be defined as a piece of code in execution. Each process has no less than one thread. So, all the processes get executed in terms of a thread. Any application will have an entry point called Main, and at the maximum, it can have only one Main. This is where an application starts. The thread which executes this Main function (i.e., starts the application) is called the main thread. This main thread can spawn any number of threads, depending upon the application requirement, to execute functionalities in parallel. Multiple threads in an application enable parallel execution. The term multiple threads signifies the total number of threads within a single process, not across different processes.</p>
<p>Multiple threads in execution is not similar to multiple process in execution. Each process has its own address space. The address space of one process cannot be used (read/write) by another process. Any communication between the processes should happen through some IPC (Inter Process Communication) mechanisms. But, multiple threads in a process share the process address space. They don't need any special mechanism for communication. They can communicate each other directly using a variable or some signals. Also, context-switching (this is how we achieve parallel execution using a single processor!!!) is time consuming to switch between processes, but not in the case of switching between threads. So, multiple threads enable parallel execution within a process effectively.</p>
<p>Do I really need multithreading?</p>
<p>Consider you have a calculator application which does some complex arithmetic operations. And, you need to provide a stop feature so that the user can stop the calculation at the middle, before letting it to finish. Having only one thread in your application is not possible to address this requirement. You can not process the stop function while you are doing an arithmetic operation. As the application will be busy with executing the arithmetic operation, it cannot handle the stop until the arithmetic operation is completed. Here, you need a thread which can execute the complex arithmetic operation, and another (the main thread) will listen to user inputs, in this case, the stop. When the main thread receives the stop signal, it can stop the thread spawned for execution of the arithmetic operation.</p>
<p>You have to be more careful when creating threads, because creating unwanted threads may reduce your application performance. Similarly, avoiding threads in required places will distress your application.</p>
<h3>1.1.2 Threading in .NET</h3>
<p>If you are familiar with delegates, you can skip this topic.</p>
<p>Before starting with threads, let's understand what delegates are. A delegate can be defined as a data type which holds an array of methods. All the methods inside a delegate should have the same signature and the same return type. The method signature and the return type of a delegate will be defined in the delegate declaration itself. The C# code for a delegate declaration is:</p>
<div class=SmallText id=premain0 style="WIDTH: 100%"><img id=preimg0 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="0"><span id=precollapse0 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="0"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="0"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre0 style="MARGIN-TOP: 0px"><span class=code-keyword>public</span> <span class=code-keyword>delegate</span> <span class=code-keyword>void</span> MyDelegate(<span class=code-keyword>int</span> arg);</pre>
<p>Here, the delegate <code>MyDelegate</code> can hold methods with the signature <code lang=cs><span class=code-keyword>void</span> <em>functionname</em>(<span class=code-keyword>int</span> k)</code>.</p>
<p>To add a function into a delegate, create the instance of the delegate and pass the function name as the argument.</p>
<div class=SmallText id=premain1 style="WIDTH: 100%"><img id=preimg1 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="1"><span id=precollapse1 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="1"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="1"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre1 style="MARGIN-TOP: 0px">MyDelegate delInstance = <span class=code-keyword>new</span> MyDelegate(Function1);</pre>
<p>Multiple functions can also be added in a delegate; to add more functions, use the <code lang=cs>+=</code> operator.</p>
<div class=SmallText id=premain2 style="WIDTH: 100%"><img id=preimg2 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="2"><span id=precollapse2 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="2"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="2"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre2 style="MARGIN-TOP: 0px">delInstance += <span class=code-keyword>new</span> MyDelegate(Function2);</pre>
<p>Here, <code>Funtion1</code> and <code>Function2</code> have the same signature as defined in the <code>MyDelegate</code> declaration. I.e., they should return <code lang=cs><span class=code-keyword>void</span></code> and take a parameter of type <code lang=cs><span class=code-keyword>int</span></code>.</p>
<p>Delegates can be invoked as normal functions, just by passing the arguments.</p>
<div class=SmallText id=premain3 style="WIDTH: 100%"><img id=preimg3 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="3"><span id=precollapse3 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="3"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="3"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre3 style="MARGIN-TOP: 0px">delInstance(<span class=code-digit>5</span>);</pre>
<p>The above line of code will invoke all the functions inside the <code>delInstance</code> delegate, sequentially. First, <code>Function1(<span class=code-digit>5</span>)</code> will be called, and then <code>Function2(<span class=code-digit>5</span>)</code>. This is called multicasting delegates, i.e., a single invoke of the delegate instance in turn calls multiple functions inside the delegate.</p>
<h3>1.1.3 Creating Threads in .NET </h3>
<p>Threads in .NET are created using the class "<code>Thread</code>". This class is available in the "<code>System.Threading</code>" namespace. To create a new thread, you need to create an instance of the <code>Thread</code> class and apply the <code>Start</code> method (available in the <code>Thread</code> class) on that instance. The <code>Thread</code> class constructor takes a <code>ThreadStart</code> delegate as a parameter. (<code>ThreadStart</code> is a delegate defined in the <code>System.Threading</code> namespace.) The signature of the <code>ThreadStart</code> delegate takes no arguments and returns <code lang=cs><span class=code-keyword>void</span></code>. So, the function to be executed in a separate thread should return <code lang=cs><span class=code-keyword>void</span></code>, and should not take any arguments.</p>
<p>The C# code for creating threads:</p>
<div class=SmallText id=premain4 style="WIDTH: 100%"><img id=preimg4 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="4"><span id=precollapse4 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="4"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="4"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre4 style="MARGIN-TOP: 0px"><span class=code-keyword>public</span> <span class=code-keyword>static</span> <span class=code-keyword>void</span> main()
{
Thread t = <span class=code-keyword>new</span> Thread(<span class=code-keyword>new</span> ThreadStart(ClassName.MyFunction));
t.Start();
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0;i&lt;100;i++)
Console.WriteLine(<span class=code-string>"</span><span class=code-string>I am in Main Thread {0}"</span>,i);
}
<span class=code-keyword>public</span> <span class=code-keyword>static</span> <span class=code-keyword>void</span> MyFunction()
{
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0;i&lt;100;i++)
Console.WriteLine(<span class=code-string>"</span><span class=code-string>I am in Different Thread {0}"</span>,i);
}</pre>
<p>In the above code, we defined a function <code>MyFunction</code> which matches the <code>ThreadStart</code> delegate signature. Then, we created an instance for the <code>Thread</code> class, passing the <code>ThreadStart</code> delegate instance. Then, we started a separate thread to execute the <code>MyFunction</code> while the main thread which spawned the <code>MyFunction</code> in a separate thread was also running.</p>
<p>On executing this, we get the console messages swapped between the main thread and a different thread since both the <code>Main</code> and <code>MyFunction</code> '<code lang=cs><span class=code-keyword>for</span></code>' loops are running in parallel.</p>
<p>This is how we create threads in .NET. Here, the <code>Thread</code> class can not take delegates of any signature as parameter, it just takes the <code>ThreadStart</code> delegate type as parameter, and the <code>ThreadStart</code> delegate can take only a function having no arguments and no return type.</p>
<p>Then, what if you want to execute a function in a thread which takes some argument? The answer for this question can be delegates.</p>
<p>Delegates have an inbuilt function called <code>BeginInvoke()</code> provided by the compiler. This function can be used for executing a function in a thread. <code>BeginInvoke</code> calls on any delegate will be executed in a separate thread.</p>
<p>The C# code follows:</p>
<div class=SmallText id=premain5 style="WIDTH: 100%"><img id=preimg5 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="5"><span id=precollapse5 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="5"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="5"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre5 style="MARGIN-TOP: 0px"><span class=code-keyword>public</span> <span class=code-keyword>void</span> MyDelegate(<span class=code-keyword>int</span> i, <span class=code-keyword>string</span> str);
<span class=code-keyword>public</span> <span class=code-keyword>static</span> <span class=code-keyword>void</span> main()
{
MyDelegate delInstance = <span class=code-keyword>new</span> MyDelegate (MyFunction);
delInstance.BeginInvoke(<span class=code-digit>100</span>,<span class=code-string>"</span><span class=code-string> I am in Delegate Thread"</span>, <span class=code-keyword>null</span>, <span class=code-keyword>null</span>);
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0;i&lt;100;i++)
Console.WriteLine(<span class=code-string>"</span><span class=code-string>I am in Main Thread {0}"</span>,i);
}
<span class=code-keyword>public</span> <span class=code-keyword>static</span> <span class=code-keyword>void</span> MyFunction(<span class=code-keyword>int</span> count, <span class=code-keyword>string</span> str)
{
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0;i&lt;count;i++)
Console.WriteLine(str + <span class=code-string>"</span><span class=code-string> {0}"</span>,i);
}</pre>
<p>In the above code, the <code>BeginInvoke</code> call on the delegate instance runs the <code>MyFunction</code> in a separate thread. The output of the above code will be, console messages swapped between the main thread and the delegate thread (similar to using the <code>Thread</code> class). Note that multicasting a delegate through <code>BeginInvoke</code> is not possible.</p>
<p>Here, our <code>MyFunction</code> returns no value. What if the function returns some value? How do we collect the return value?</p>
<p>As <code>BeginInvoke</code> is an asynchronous call (just triggers the other thread and keeps running the next line, not waiting to finish the other thread), it cannot get the return value of the function call directly. So, we need some mechanism to collect the return value. The implementation of the <code>BeginInvoke</code> function in C# returns an <code>IAsyncResult</code> type. This <code>IAsyncResult</code> can be used for getting the return value, when required. There is a function called <code>EndInvoke</code>, which takes this <code>IAsynResult</code> as argument and collects the return value. So, the <code>EndInvoke</code> function can be used to collect the return value.</p>
<p>Every <code>EndInvoke</code> should be associated with a <code>BeginInvoke</code> as <code>EndInvoke</code> operates on the return value of <code>BeginInvoke</code>.</p>
<p>The return value can be collected with the following C# code:</p>
<div class=SmallText id=premain6 style="WIDTH: 100%"><img id=preimg6 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="6"><span id=precollapse6 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="6"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="6"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre6 style="MARGIN-TOP: 0px"><span class=code-keyword>public</span> <span class=code-keyword>bool</span> MyDelegate(<span class=code-keyword>int</span> i, <span class=code-keyword>string</span> str);
<span class=code-keyword>public</span> <span class=code-keyword>static</span> <span class=code-keyword>void</span> main()
{
MyDelegate delInstance = <span class=code-keyword>new</span> MyDelegate (MyFunction);
IAsyncResult <span class=code-keyword>ref</span> = delInstance.BeginInvoke(<span class=code-digit>100</span>,
<span class=code-string>"</span><span class=code-string>I am in Delegate Thread"</span>, <span class=code-keyword>null</span>, <span class=code-keyword>null</span>);
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0;i&lt;100;i++)
Console.WriteLine(<span class=code-string>"</span><span class=code-string>I am in Main Thread {0}"</span>,i);
<span class=code-keyword>bool</span> status = delInstance.EndInvoke(<span class=code-keyword>ref</span>);
}
<span class=code-keyword>public</span> <span class=code-keyword>static</span> <span class=code-keyword>bool</span> MyFunction(<span class=code-keyword>int</span> count, <span class=code-keyword>string</span> str)
{
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0;i&lt;count;i++)
Console.WriteLine(str + <span class=code-string>"</span><span class=code-string> {0}"</span>,i);
<span class=code-keyword>return</span> <span class=code-keyword>true</span>;
}</pre>
<p>In the above code, the call to the <code>EndInvoke</code> function takes the <code>IsyncResult</code> type returned by the <code>BeginInvoke</code>, and returns the value returned by the <code>MyFunction</code>. Thus, the <code>EndInvoke</code> can be used to obtain the result of <code>BeginInvoke</code>.</p>
<p>Consider the following program in C#:</p>
<div class=SmallText id=premain7 style="WIDTH: 100%"><img id=preimg7 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="7"><span id=precollapse7 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="7"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="7"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre7 style="MARGIN-TOP: 0px"><span class=code-keyword>public</span> <span class=code-keyword>void</span> MyDelegate(<span class=code-keyword>int</span> i, <span class=code-keyword>string</span> str);
<span class=code-keyword>public</span> <span class=code-keyword>static</span> <span class=code-keyword>void</span> main()
{
MyDelegate delInstance = <span class=code-keyword>new</span> MyDelegate (MyFunction);
delInstance.BeginInvoke(<span class=code-digit>1000</span>, <span class=code-string>"</span><span class=code-string>I am in Delegate Thread"</span>, <span class=code-keyword>null</span>, <span class=code-keyword>null</span>);
}
<span class=code-keyword>public</span> <span class=code-keyword>static</span> <span class=code-keyword>void</span> MyFunction(<span class=code-keyword>int</span> count, <span class=code-keyword>string</span> str)
{
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0;i&lt;count;i++)
Console.WriteLine(str + <span class=code-string>"</span><span class=code-string> {0}"</span>,i);
}</pre>
<p>If we look at the program closely, the main thread finishes its execution before the other thread is finished. When the main thread is destroyed, all the other threads automatically get destroyed. So, you may not get the desired output. To avoid this problem, we can use <code>EndInvoke</code>. The <code>EndInvoke</code> function can also be used for blocking the current thread until the corresponding thread finishes its execution. A call to <code>EndInvoke</code> will block the current thread.</p>
<p>The C# code using <code>EndInvoke</code> to block the thread follows:</p>
<div class=SmallText id=premain8 style="WIDTH: 100%"><img id=preimg8 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="8"><span id=precollapse8 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="8"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="8"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre8 style="MARGIN-TOP: 0px"><span class=code-keyword>public</span> <span class=code-keyword>void</span> MyDelegate(<span class=code-keyword>int</span> i, <span class=code-keyword>string</span> str);
<span class=code-keyword>public</span> <span class=code-keyword>static</span> <span class=code-keyword>void</span> main()
{
MyDelegate delInstance = <span class=code-keyword>new</span> MyDelegate (MyFunction);
ISyncResult <span class=code-keyword>ref</span> = delInstance.BeginInvoke(<span class=code-digit>100</span>,<span class=code-string>"</span><span class=code-string> I am in Delegate Thread"</span>,
<span class=code-keyword>null</span>, <span class=code-keyword>null</span>);
delInstance.EndInvoke(<span class=code-keyword>ref</span>);
}
<span class=code-keyword>public</span> <span class=code-keyword>static</span> <span class=code-keyword>void</span> MyFunction(<span class=code-keyword>int</span> count, <span class=code-keyword>string</span> str)
{
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0;i&lt;count;i++)
Console.WriteLine(str + <span class=code-string>"</span><span class=code-string> {0}"</span>,i);
}</pre>
<p>In the above code, the call to the <code>EndInvoke</code> blocks the main thread until the <code>MyFunction</code> is completed.</p>
<p>A call to <code>EndInvoke</code> will collect the return value immediately if the thread has completed its execution already; otherwise, it will wait until the thread is completed and gets the result.</p>
<p>While making the call to <code>BeginInvoke</code>, we have not created any thread, then who is creating the thread? How does it run in a separate thread?</p>
<p>To answer these questions, let's first know what thread pools are.</p>
<h3>1.1.4 Thread Pool</h3>
<p>Creating a thread at runtime is not an easy job. Most of the time will be spent on creating the thread rather than executing the functionality on the thread, in the case of smaller threads.</p>
<p>The CLR (Common Language Runtime) has some threads created already in a pool so that they can be used whenever required. These threads are called Thread Pool threads. If we are using a thread in the thread pool, on completion of a thread, the thread will not be destroyed. The thread will return to the thread pool in suspended state. This suspended thread can be reused for other purposes.</p>
<p>The <code>BeginInvoke</code> function uses these Thread Pool threads to execute functionalities. The usage of thread pool threads saves the thread creation time.</p>
<h2>1.2 Threading in WinForms</h2>
<p>In section 1.1, we saw how to create a thread using the <code>Thread</code> class and delegates. In this section, let us see how to handle threads in WinForms. (This article assumes that you have worked on WinForms applications.)</p>
<h3>1.2.1 WinForms Internals</h3>
<p>Before starting with the threads directly, let's understand how a Windows application works. Consider you have a Windows application where you create a text box and add the text box to the form. The C# code follows:</p>
<div class=SmallText id=premain9 style="WIDTH: 100%"><img id=preimg9 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="9"><span id=precollapse9 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="9"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="9"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre9 style="MARGIN-TOP: 0px">Form1_Load(&#8230;&#8230;)
{
AddControl();
}
Void AddControl()
{
TextBox textBox1 = <span class=code-keyword>new</span> TextBox();
Controls.add(textBox1);
}</pre>
<p>On loading the form, the <code>AddControl</code> function is invoked, and it creates a text box and adds it to the form using the <code>Controls.Add</code> method.</p>
<p>The above code will run without any errors.</p>
<p>Consider the same application, where we would like to call the <code>AddControl()</code> method in a thread. The C# code follows:</p>
<div class=SmallText id=premain10 style="WIDTH: 100%"><img id=preimg10 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="10"><span id=precollapse10 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="10"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="10"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre10 style="MARGIN-TOP: 0px">Form1_Load(&#8230;&#8230;)
{
Thread t = <span class=code-keyword>new</span> Thread(<span class=code-keyword>new</span> ThreadStart(RunInThread));
t.Start();
}
Void RunInThread()
{
AddControl();
}
Void AddControl()
{
TextBox textBox1 = <span class=code-keyword>new</span> TextBox();
controls.add(textBox1);
}</pre>
<p>There is no change, except we call the function <code>AddControl</code> from a separate thread (not from the main thread). Here, the functions <code>RunInThread</code> and <code>AddControl</code> run in the same thread. If you try to run the above code, though the code will compile without any errors, you will receive a runtime error saying: "Controls created on one thread cannot be parented to a control on a different thread." This is what we should worry about when dealing with threads in WinForms.</p>
<p>So, why do we get this runtime error? A rule in Windows is that "a control created on one thread cannot be modified in another thread". In the second example, the form was created in the main thread, and we were trying to modify the form object from another thread. That is a violation of the Windows rule (why do we have the rule is a different topic to explain). It throws the runtime error as we tried to update the control from a different thread. We can simply say that any update on the UI should happen only through the main thread.</p>
<p>Then, how do we update the UI while we are in a different thread? Before looking at the answer, let us understand how Windows applications work.</p>
<p>All Windows applications have two queue structures, the send message queue and the post message queue. These queues will have actions to be performed. The main thread is responsible for executing all the tasks in the queue. The main thread will dequeue the messages one by one and executes them.</p>
<ul>
    <li>Post Message Queue
    <li>Send Message Queue
    <li>Main Thread </li>
</ul>
<p>The post message queue will have messages posted through the <code>PostMessage</code> function. Similarly, the send message queue will have messages posted by the <code>SendMessage</code> function. The difference between <code>SendMessage</code> and <code>PostMessage</code> is that <code>SendMessage</code> will block the call until it is executed. But <code>PostMessage</code> just puts the message in the queue and returns. The main thread first executes the send message queue messages and then it starts executing the post message queue messages.</p>
<p>So, the answer for our question on how to update the UI while we are in different thread is to put it in the message queue. The next question is how to post/send a message in .NET?</p>
<p>Answering this question is very simple. A <code>Control</code> class has three methods:</p>
<ul class=method>
    <li><code>Invoke</code>
    <li><code>BeginInvoke</code>
    <li><code>EndInvoke</code> </li>
</ul>
<p>The <code>Invoke</code> method does <code>SendMessage</code>. The <code>BeginInvoke</code> method does <code>PostMessage</code>. The <code>EndInvoke</code> method is used as part of <code>BeginInvoke</code> to obtain the results of the <code>BeginInvoke</code> call (as discussed in section 1.1).</p>
<h3>1.2.2 Control.Invoke</h3>
<p>As mentioned earlier, the <code>Invoke</code> method on the <code>Control</code> class places a calls into the send message queue. The call will ultimately be executed by the main thread, and the <code>Invoke</code> method will block the current thread until the call is returned.</p>
<p>The <code>Invoke</code> method on the <code>Control</code> class has two overloads:</p>
<ul class=method>
    <li><code lang=cs><span class=code-keyword>public</span> System.<span class=code-SDKkeyword>Object</span> Invoke ( System.Delegate method )</code>
    <li><code lang=cs><span class=code-keyword>public</span> <span class=code-keyword>virtual</span> <span class=code-keyword>new</span> System.<span class=code-SDKkeyword>Object</span> Invoke ( System.Delegate method , <span class=code-keyword>object</span>[] args )</code> </li>
</ul>
<p>The argument takes the delegate to be executed on the Main thread. If the parameters need to be passed for the delegate, they can be passed as an <code lang=cs><span class=code-keyword>object</span></code> array. The return value can also be obtained as an <code lang=cs><span class=code-keyword>object</span></code>.</p>
<p>Now, let's go back to the program:</p>
<div class=SmallText id=premain11 style="WIDTH: 100%"><img id=preimg11 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="11"><span id=precollapse11 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="11"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="11"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre11 style="MARGIN-TOP: 0px"><span class=code-keyword>public</span> <span class=code-keyword>delegate</span> <span class=code-keyword>void</span> MyDelegate();
Form_Load(&#8230;&#8230;)
{
Thread t = <span class=code-keyword>new</span> Thread(<span class=code-keyword>new</span> ThreadStart(RunInThread));
t.Start();
}
<span class=code-keyword>void</span> RunInThread ()
{
MyDelagate delInstatnce = <span class=code-keyword>new</span> MyDelagate(AddControl);
<span class=code-keyword>this</span>.Invoke(delInstatnce);
MessageBox.Show(<span class=code-string>"</span><span class=code-string>Hello"</span>);
<span class=code-comment>//</span><span class=code-comment>Add your code that needs to be executed in separate thread </span>
<span class=code-comment>//</span><span class=code-comment>except UI updation</span>
}
<span class=code-keyword>void</span> AddControl()
{
TextBox textBox1 = <span class=code-keyword>new</span> TextBox();
Controls.add(textBox1);
}</pre>
<p>Here, we try to execute the <code>AddControl</code> function in a different thread, using the <code>RunInThread</code> function. The <code>RunInThread</code> function is executed in a separate thread. We try to call the <code>AddControl</code> function inside the <code>RunInThread</code> function through a delegate. Though the <code>RunInThread</code> function runs in a separate thread, <code lang=cs><span class=code-keyword>this</span>.Invoke</code> (here, the '<code lang=cs><span class=code-keyword>this</span></code>' means the <code>Form</code> object) puts the function to be executed in the send message queue. So, the function is ultimately executed in the main thread in which the form was created. So, it never throws an exception. (Note that, here the <code>AddControl</code> and <code>RunInThread</code> functions are not executed in the same thread.) The call to the <code>Invoke</code> function will block the current thread until the <code>AddControl</code> function is completed fully, i.e., the message box will appear only after the complete execution of the <code>AddControl</code> call.</p>
<h3>1.2.3 Control.BeginInvoke</h3>
<p>As seen earlier, the <code>BeginInvoke</code> method on the <code>Control</code> class places the call into the post message queue. This call will ultimately be executed by the main thread, and the <code>BeginInvoke</code> method will not block the current thread as <code>Invoke</code> does. It will start executing the next line after placing the call in the post message queue. The return value can be collected using the <code>EndInvoke</code> method.</p>
<p>Similar to the <code>Invoke</code> method, <code>BeginInvoke</code> has two overloads in the <code>Control</code> class:</p>
<ul class=method>
    <li><code lang=cs><span class=code-keyword>public</span> System.IAsyncResult BeginInvoke ( System.Delegate method )</code>
    <li><code lang=cs><span class=code-keyword>public</span> <span class=code-keyword>virtual</span> <span class=code-keyword>new</span> System.IAsyncResult BeginInvoke ( System.Delegate method , <span class=code-keyword>object</span>[] args )</code> </li>
</ul>
<p>The arguments are similar to those of <code>BeginInvoke</code>, but the return type here is <code>IAsynResult</code>. This <code>IAsynresult</code> can be used for collecting the result using <code>EndInvoke</code>.</p>
<div class=SmallText id=premain12 style="WIDTH: 100%"><img id=preimg12 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="12"><span id=precollapse12 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="12"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="12"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre12 style="MARGIN-TOP: 0px">Public <span class=code-keyword>delegate</span> <span class=code-keyword>void</span> MyDelegate();
Form_Load(&#8230;&#8230;)
{
Thread t = <span class=code-keyword>new</span> Thread(<span class=code-keyword>new</span> ThreadStart(RunInThread));
t.Start();
}
<span class=code-keyword>void</span> RunInThread()
{
MyDelagate delInstatnce = <span class=code-keyword>new</span> MyDelagate(AddControl);
<span class=code-keyword>this</span>.BeginInvoke(delInstatnce);
MessageBox.Show(<span class=code-string>"</span><span class=code-string>Hello"</span>);
}
<span class=code-keyword>void</span> AddControl()
{
TextBox textBox1 = <span class=code-keyword>new</span> TextBox();
Controls.add(textBox1);
}</pre>
<p>Since we have used the <code>BeginInvoke</code> here, we could see the message box displayed before the <code>AddControl</code> is completed.</p>
<p>Consider the following C# code:</p>
<div class=SmallText id=premain13 style="WIDTH: 100%"><img id=preimg13 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="13"><span id=precollapse13 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="13"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="13"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre13 style="MARGIN-TOP: 0px"><span class=code-keyword>public</span> <span class=code-keyword>delegate</span> <span class=code-keyword>void</span> MyDelegate();
Form_Load(&#8230;&#8230;)
{
MyDelagate delInstatnce = <span class=code-keyword>new</span> MyDelagate(AddControl);
<span class=code-keyword>this</span>.BeginInvoke(delInstatnce);
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0; i&lt;1000; i++)
textBox1.Text += <span class=code-string>"</span><span class=code-string>Main "</span> + i.ToString();
}
<span class=code-keyword>void</span> AddControl()
{
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0; i&lt;1000; i++)
textBox1.Text += <span class=code-string>"</span><span class=code-string>Thread "</span> + i.ToString();
}</pre>
<p>The above code will not run in parallel, since both the loops have to run in the main thread. First, it will print all the <code>Form_Load</code> '<code lang=cs><span class=code-keyword>for</span></code>' loop messages, and then it will print the <code>AddControl</code> '<code lang=cs><span class=code-keyword>for</span></code>' loop messages.</p>
<p>Consider the same C# code for the <code>Invoke</code> call:</p>
<div class=SmallText id=premain14 style="WIDTH: 100%"><img id=preimg14 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="14"><span id=precollapse14 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="14"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="14"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre14 style="MARGIN-TOP: 0px"><span class=code-keyword>public</span> <span class=code-keyword>delegate</span> <span class=code-keyword>void</span> MyDelegate();
Form_Load(&#8230;&#8230;)
{
MyDelagate delInstatnce = <span class=code-keyword>new</span> MyDelagate(AddControl);
<span class=code-keyword>this</span>.Invoke(delInstatnce);
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0; i&lt;1000; i++)
textBox1.Text += <span class=code-string>"</span><span class=code-string>Main "</span> + i.ToString();
}
<span class=code-keyword>void</span> AddControl()
{
<span class=code-keyword>for</span>(<span class=code-keyword>int</span> i=0; i&lt;1000; i++)
textBox1.Text += <span class=code-string>"</span><span class=code-string>Thread "</span> + i.ToString();
}</pre>
<p>The above code will not run in parallel either, since both the loops have to run in the main thread. First, it will print all the <code>AddControl</code> '<code lang=cs><span class=code-keyword>for</span></code>' loop messages, and then it will print the <code>Form_Load</code> '<code lang=cs><span class=code-keyword>for</span></code>' loop messages. As opposed to the earlier one, the <code>Invoke</code> method blocks the call.</p>
<h3>1.2.4 Control.InvokeRequired</h3>
<p>Consider the following C# code:</p>
<div class=SmallText id=premain15 style="WIDTH: 100%"><img id=preimg15 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="15"><span id=precollapse15 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="15"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="15"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre15 style="MARGIN-TOP: 0px">Form_Load(&#8230;&#8230;)
{
MyDelagate delInstatnce = <span class=code-keyword>new</span> MyDelagate(AddControl);
<span class=code-keyword>this</span>.Invoke(delInstatnce);
}
<span class=code-keyword>void</span> AddControl()
{
TextBox textBox1 = <span class=code-keyword>new</span> TextBox();
Controls.add(textBox1);
}</pre>
<p>In the above code, we unnecessarily use the <code>Invoke</code> method, though we are there in the main thread already. Here, we know that we are in the main thread, and we can avoid using <code>Invoke</code>/<code>BeginInvoke</code>. But in some cases, we don't know whether the particular function will be executed by the main thread or by some other thread. And, the caller doesn't know whether the particular function has any UI update code. So, the function which updates the UI should take care of taking the current thread to the main thread. For that purpose, we have a member "<code>InvokeRequired</code>" in the <code>Control</code> class which returns <code lang=cs><span class=code-keyword>true</span></code> if the current thread is not the main thread, <code lang=cs><span class=code-keyword>false</span></code> if the current thread is the main thread. So, any update in the UI should happen through the <code>InvokeRequired</code> property as a safe coding practice. The caller won't handle the <code>Invoke</code> methods, rather the implementation inside the function will do.</p>
<p>The C# code follows:</p>
<div class=SmallText id=premain16 style="WIDTH: 100%"><img id=preimg16 style="CURSOR: pointer" height=9 src="http://www.codeproject.com/images/minus.gif" width=9 preid="16"><span id=precollapse16 style="MARGIN-BOTTOM: 0px; CURSOR: pointer" preid="16"> Collapse</span><img style="MARGIN-LEFT: 35px" height=16 src="http://www.codeproject.com/images/copy_16.png" width=16><a href="http://www.codeproject.com/KB/threads/Threading.aspx#" preid="16"><u><font color=#800080> Copy Code</font></u></a></div>
<pre lang=cs id=pre16 style="MARGIN-TOP: 0px">Form_Load(&#8230;&#8230;) <span class=code-comment>//</span><span class=code-comment>this function runs in main thread.</span>
{
AddControl();
}
<span class=code-keyword>void</span> RunInThread() <span class=code-comment>//</span><span class=code-comment>this function runs in a different thread.</span>
{
AddControl();
}
<span class=code-keyword>void</span> AddControl()
{
<span class=code-keyword>if</span>(<span class=code-keyword>this</span>.InvokeRequired)
{
MyDelagate delInstatnce = <span class=code-keyword>new</span> MyDelagate(AddControl);
<span class=code-keyword>this</span>.Invoke(delInstatnce);
<span class=code-keyword>return</span>;
}
TextBox textBox1 = <span class=code-keyword>new</span> TextBox();
Controls.add(textBox1);
}</pre>
<p>Here, the caller just calls the function, but the function implementation takes the current thread to the main thread, if required. In the above code, the <code>Form_Load</code> call to <code>AddControl</code> won't use the <code>Invoke</code> method but the <code>RunInThread</code> call to <code>AddControl</code> will use the delegate <code>Invoke</code> method.</p>
<p>The <code>BeginInvoke</code> available in the delegate and the <code>BeginInvoke</code> available in the <code>Control</code> class are not the same. The <code>BeginInvoke</code> on the delegates uses the thread pool threads to execute the function in parallel. But the <code>BeginInvoke</code> in the <code>Control</code> class just posts a message in the message queue. It will not create a separate thread to run the function. So, the delegate <code>BeginInvoke</code> may enable parallelism, but the <code>Control</code> <code>BeginInvoke</code> may not.</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/51342.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-11-11 21:55 <a href="http://www.cnitblog.com/seeyeah/archive/2008/11/11/51342.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>winform下提高control在UI中的响应速度 </title><link>http://www.cnitblog.com/seeyeah/archive/2008/11/10/51306.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 10 Nov 2008 15:09:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/11/10/51306.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/51306.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/11/10/51306.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/51306.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/51306.html</trackback:ping><description><![CDATA[摘至：<a href="http://www.cnblogs.com/juqiang/archive/2008/09/28/41871.html">http://www.cnblogs.com/juqiang/archive/2008/09/28/41871.html</a><br>
<hr>
<br><br>其实有很多种办法，先列出第一种性能最差，也是我们经常写的代码：<br>
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<div><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;count&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">10000</span><span style="COLOR: #000000">;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;button1_Click(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">&nbsp;sender,&nbsp;System.EventArgs&nbsp;e)<br><img id=Codehighlighter1_93_294_Open_Image onclick="this.style.display='none'; Codehighlighter1_93_294_Open_Text.style.display='none'; Codehighlighter1_93_294_Closed_Image.style.display='inline'; Codehighlighter1_93_294_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_93_294_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_93_294_Closed_Text.style.display='none'; Codehighlighter1_93_294_Open_Image.style.display='inline'; Codehighlighter1_93_294_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_93_294_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_93_294_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;l1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;System.DateTime.Now.Ticks;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Items.Clear();<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">count;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)listBox1.Items.Add(i);<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;l2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;System.DateTime.Now.Ticks;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageBox.Show((l2</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">l1).ToString());<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
</div>
这是我以前在cbuilder中经常使用的方式：<br>
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<div><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;l1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;System.DateTime.Now.Ticks;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Enabled&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Visible&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Items.Clear();<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">count;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)listBox1.Items.Add(i);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Enabled&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Visible&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;l2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;System.DateTime.Now.Ticks;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageBox.Show((l2</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">l1).ToString());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div>
</div>
<br>这种方式，值得注意的是，如果你没有设置Visible=false，效率和第一种差不多。<br>这是.net下推荐的方式：<br>
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<div><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;l1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;System.DateTime.Now.Ticks;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.BeginUpdate();<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Items.Clear();<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">count;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)listBox1.Items.Add(i);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.EndUpdate();<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;l2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;System.DateTime.Now.Ticks;<br><img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageBox.Show((l2</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">l1).ToString());</span></div>
</div>
<br>对于如上面简单的control，大家可以测试一下，第一和最后一种，差2、3倍的时间是没有问题的。而如果我们使用诸如datagrid这种control，再如果我们的每个cell中作了不少事件的handle，那么，效率是非常低的。常见的现象，你看见datagrid上的cell光标，四处乱跑。<br>而BeginUpdate/EndUpdate，在这个范围段内，不响应任何事件（此处我也存疑，呵呵）。如果没有event的handle，那么慢的唯一原因是UI需要不停的刷新。所以第二种的方式下，让它disable/invisible，也是可以解决这个问题的。<br>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/51306.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-11-10 23:09 <a href="http://www.cnitblog.com/seeyeah/archive/2008/11/10/51306.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跨线程操作GUI </title><link>http://www.cnitblog.com/seeyeah/archive/2008/11/04/51021.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 03 Nov 2008 16:09:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/11/04/51021.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/51021.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/11/04/51021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/51021.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/51021.html</trackback:ping><description><![CDATA[摘至：<a href="http://www.cnblogs.com/taowen/archive/2008/11/03/1325010.html">http://www.cnblogs.com/taowen/archive/2008/11/03/1325010.html</a><br>
<hr>
<p>无论是WIN32还是Windows Form还是WPF还是Swing，都不支持GUI线程之外的线程直接访问其API。今天我们来回顾一下这个发展过程。一个普通的操作是怎么被封装封装再封装的。</p>
<h3>Win32</h3>
<p>在Windows SDK时代，我们都知道，界面就是一个大的WndProc控制的。</p>
<div class=cnblogs_code>
<pre><span id=Code_Open_Text_202604><span style="COLOR: #0000ff">switch</span><span style="COLOR: #000000"> (message)<br>{<br>        </span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000"> WM_PAINT:<br><img alt="" src="http://images.cnblogs.com/dot.gif"><br>        </span><span style="COLOR: #0000ff">case</span><span style="COLOR: #000000"> WM_DESTROY:<br><img alt="" src="http://images.cnblogs.com/dot.gif"><br>        </span><span style="COLOR: #0000ff">default</span><span style="COLOR: #000000">:<br>            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> DefWindowProc(hWnd, message, wParam, lParam);<br>}</span></span></pre>
</div>
<p>如果我们需要另外一个线程去做一些耗时的IO操作，同时要回调回来更新的界面，这个时候要么自己定义一个回调队列，然后在WM_IDLE的时候处理，要么就利用窗口本身的消息队列，自己创建一个消息类型：</p>
<div class=cnblogs_code>
<pre><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> at startup</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> OUR_APP_IO_COMPLETED </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> RegisterWindowMessage(</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">OUR_APP_IO_COMPLETED</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #000000">----</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> after io completed</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">PostMessage(hwnd, OUR_APP_IO_COMPLETED, xxx, xxx);</span></pre>
</div>
<p>这样，我们就可以让界面更新的操作在GUI线程完成了。</p>
<h3>.NET 1.0 Windows Forms</h3>
<p>Windows Forms的出现使得很多东西简单多了。跨线程的GUI操作也简化了许多。因为我们有了Delegate和Control.Invoke。前者就是一个函数指针的升级版，Control.Invoke就是PostMessage的升级版：</p>
<div class=cnblogs_code>
<pre><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">delegate</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> IOCompletedHandler();<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> OnIOCompleted() {<br>  control.Invoke(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> IOCompletedHandler(HandleIOCompleted));<br>}<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> HandleIOCompleted() {<br><img alt="" src="http://images.cnblogs.com/dot.gif"><br>}</span></pre>
</div>
<p>在内部Control维护了一个threadCallbackList。调用Invoke相当于</p>
<p>1、把Delegate和参数封装到一起，压入到threadCallbackList中</p>
<p>2、确保ThreadCallbackMessage被注册了（RegisterWindowMessage）</p>
<p>3、PostMessage，触发Callback</p>
<p>4、WaitForHandle，等待GUI线程完成处理（如果是BeginInvoke则可以省略这个步骤）</p>
<p>而Windows Forms的WndProc的消息循环，就需要加一个case语句，来响应PostMessage。在得到消息的同时，去threadCallbackList中取出需要回调的Delegate，然后一一调用。</p>
<p>Control.Invoke确实是让我们的生活方便很多。但是它还是不能避免所谓的BeginInvoke之舞（BeginInvoke Dance）：</p>
<div class=cnblogs_code>
<pre><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #0000ff"><span style="COLOR: #008000">//http://ikriv.com:8765/en/prog/info/dotnet/MysteriousHang.html</span><br>delegate</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> MyHandlerDelegate();        <br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> MyHandler()<br>{<br>    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> "The BeginInvoke dance"</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.InvokeRequired) </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> assuming this descends from Control</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">    {<br>        BeginInvoke( </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> MyHandlerDelegate(MyHandler) );<br>        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br>    }<br>    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> assume we are on the main GUI thread</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">    <img alt="" src="http://images.cnblogs.com/dot.gif"> </span><span style="COLOR: #0000ff">do</span><span style="COLOR: #000000"> GUI stuff <img alt="" src="http://images.cnblogs.com/dot.gif"><br>}</span></pre>
</div>
<p>InvokeRequired内部实现就是线程安全地比较一下当前线程和GUI线程的线程ID是不是相等的。</p>
<p>另外Control.Invoke还需要我们确保对应的Control的句柄已经创建。为了避免这个问题，WinForm有一个MarshingControl可以给我们使用。</p>
<p>&nbsp;</p>
<div class=cnblogs_code>
<pre><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #000000">Application.ThreadContext.FromCurrent().MarshingControl;</span></pre>
</div>
<p>&nbsp;</p>
<h3>.NET 2.0 Windows Forms</h3>
<p>如果我提供了一个回调接口。我一般会直接调用回调方法，如果我知道回调方法必须在GUI线程中执行的话，用必须用Control.Invoke来调用回调方法。所以，在缺乏信息的情况下，回调接口的提供者是没有办法保证回调方法的执行线程的环境的。所以，按照Strategy模式，我们可以定义一个CallbackStrategy</p>
<div class=cnblogs_code>
<pre><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">interface</span><span style="COLOR: #000000"> CallbackExecutor {<br>  </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> Execute(Delegate callback, </span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">[] args);<br>}<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> DefaultCallbackExecutor : CallbackExecutor {<br>  </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> Execute(Delegate callback, </span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">[] args) {<br>    callback.Invoke(args);<br>  }<br>}<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> WindowsFormsCallbackExecutor : CallbackExecutor {<br>   </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Control marshalingControl;<br>   </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> WindowsFormsCallbackExecutor() {<br>     Application.ThreadContext context </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> Application.ThreadContext.FromCurrent();<br>        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (context </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)<br>        {<br>            </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.marshalingControl</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> context.MarshalingControl;<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"> Execute(Delegate callback, </span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000">[] args) {<br>     marshalingControl.Invoke(callback, args);<br>  }<br>}</span></pre>
</div>
<p>然后回调方法的提供者就不用为难了，它只要调用CallbackExecutor就可以了，同时回调方法也可以安心地直接去干自己的事情。从而，谁都不需要做BeginInvoke Dance了。</p>
<p>这就是.NET引入的SynchronizationContext的基本原理。由于微软不是接口爱好者，所以它省去了共同的那个接口，直接让WindowsFormSynchronizationContext继承自SynchronizationContext类了。SynchronizationContext是线程唯一的，取得当前线程的Sync Context可以使用：</p>
<p>&nbsp;</p>
<div class=cnblogs_code>
<pre><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #000000">SynchronizationContext.Current.Post(delegate{//your code}, null);</span></pre>
</div>
<p>&nbsp;</p>
<p>与SynchronizationContext类同时引入的还有AsyncOperationManager，AsyncOperation。它又是SynchronizationContext的封装。一般来说，推荐使用AsyncOperationManager。AsyncOperationManager在创建AsyncOperation的时候会取得当前线程的Sync Context，并存储在SyncOperation之中。 所以后来利用AsyncOperation来回调的时候，就会用一开始创建时候所在线程的context来回调。</p>
<div class=cnblogs_code>
<pre><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> initialize in GUI thread</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">asyncOperation </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> AsyncOperationManager.Create(</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">);<br><img alt="" src="http://images.cnblogs.com/dot.gif"><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> when you want to call back</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">asyncOperation.Post(</span><span style="COLOR: #0000ff">delegate</span><span style="COLOR: #000000">{</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">your code}, null);</span></pre>
</div>
<p>像BackgroundWorker这样的类，之所以其Callback可以直接访问GUI，其秘诀就在于回调不是直接调用的，而是有 AsyncOperation来间接代劳的。只要AsyncOperation是在GUI线程创建的，所有由它代劳的回调都会经过 MarshalingControl来做Control.Invoke。</p>
<h3>.NET 3.0 WPF</h3>
<p>Control.Invoke变成了Dispatcher.Invoke。内部实现还是一样的，有一个Callback队列，然后PostMessage。同时引入的还有DispatcherSynchronizationContext。</p>
<h3>Conculsion</h3>
<p>从直接PostMessage到Control.Invoke到SynchronizationContext到AsyncOperationManager到BackgroundWorker，职责最终推卸到了回调的提供方。但是由于引入的时间不一致，很多回调提供方是没有使用AsyncOperation的。这个时候，我们自己需要自己去包装，比如：</p>
<div class=cnblogs_code>
<pre><img id=Code_Closed_Image_075625 onclick="this.style.display='none'; document.getElementById('Code_Closed_Text_075625').style.display='none'; document.getElementById('Code_Open_Image_075625').style.display='inline'; document.getElementById('Code_Open_Text_075625').style.display='inline';" height=16 alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" width=11 align=top><img id=Code_Open_Image_075625 style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_075625').style.display='none'; getElementById('Code_Closed_Image_075625').style.display='inline'; getElementById('Code_Closed_Text_075625').style.display='inline';" height=16 alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" width=11 align=top><span class=cnblogs_code_Collapse id=Code_Closed_Text_075625>Code</span><span id=Code_Open_Text_075625 style="DISPLAY: none"><br><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> System;<br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> System.ComponentModel;<br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> System.Net;<br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> log4net;<br><br></span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000"> xxx<br>{<br>    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> WebClientFileUploader : FileUploaderListeners, FileUploader<br>    {<br>        </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">readonly</span><span style="COLOR: #000000"> ILog LOGGER </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> LogManager.GetLogger(</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000"> (WebClientFileUploader));<br>        </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">readonly</span><span style="COLOR: #000000"> WebClient webClient;<br>        </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">readonly</span><span style="COLOR: #000000"> Uri address;<br>        </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">readonly</span><span style="COLOR: #000000"> AsyncOperation asyncOperation;<br><br>        </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> WebClientFileUploader(Uri address)<br>        {<br>            asyncOperation </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> AsyncOperationManager.CreateOperation(</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">);<br>            webClient </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> WebClient();<br>            webClient.UploadFileCompleted </span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000"> HandleUploadFileCompleted;<br>            </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.address </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> address;<br>        }<br><br>        </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> HandleUploadFileCompleted(</span><span style="COLOR: #0000ff">object</span><span style="COLOR: #000000"> sender, UploadFileCompletedEventArgs eventArgs)<br>        {<br>            </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"><br>            {<br>                var result </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> eventArgs.Result;<br>                LOGGER.Info(</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">Request completed.</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">);<br>                asyncOperation.Post(state </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> HandleCompleted(result), </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">);<br>            }<br>            </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (Exception exception)<br>            {<br>                LOGGER.Error(</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">Request failed.</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">, exception);<br>                asyncOperation.Post(state </span><span style="COLOR: #000000">=&gt;</span><span style="COLOR: #000000"> HandleError(exception), </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">);<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"> Cancel()<br>        {<br>            LOGGER.Info(</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">Cancelling the request.</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">);<br>            webClient.CancelAsync();<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"> Upload(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000"> fileName)<br>        {<br>            LOGGER.Info(</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">Starting to upload to </span><span style="COLOR: #800000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> address </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">"</span><span style="COLOR: #800000"> with file </span><span style="COLOR: #800000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> fileName </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #800000">"</span><span style="COLOR: #800000"> using real web client.</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">);<br>            webClient.UploadFileAsync(address, WebRequestMethods.Http.Post, fileName);<br>        }<br>    }<br>}</span></span></pre>
</div>
<p>这样，我们就不需要在手工地去用Control.Invoke了，也不应该再直接用Control.Invoke了</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/51021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-11-04 00:09 <a href="http://www.cnitblog.com/seeyeah/archive/2008/11/04/51021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐一款DataGridView的打印解决方案 </title><link>http://www.cnitblog.com/seeyeah/archive/2008/10/22/50583.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 22 Oct 2008 15:36:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/10/22/50583.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/50583.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/10/22/50583.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/50583.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/50583.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 摘至：推荐一款DataGridView的打印解决方案 今天有朋友请教在CS的WinForm中如何打印DataGridView中的内容。网上搜索一番之后，还是在藏宝库CodeProject中找到一篇好文章《DataGridView Printing by Selecting Columns and Rows》（http://www.codeproject.com/KB/grid/PrintD...&nbsp;&nbsp;<a href='http://www.cnitblog.com/seeyeah/archive/2008/10/22/50583.html'>阅读全文</a><img src ="http://www.cnitblog.com/seeyeah/aggbug/50583.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-10-22 23:36 <a href="http://www.cnitblog.com/seeyeah/archive/2008/10/22/50583.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决log4net独占日志文件的问题以及 log4net的各种输出配置(Appender) </title><link>http://www.cnitblog.com/seeyeah/archive/2008/10/16/50334.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 16 Oct 2008 14:47:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/10/16/50334.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/50334.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/10/16/50334.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/50334.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/50334.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 摘至：http://www.cnblogs.com/jacktu/archive/2007/12/05/984487.html由于log4net默认情况下会独占日志文件，该文件不能被File.Open。可以通过增加配置：&lt;lockingModel type="log4net.Appender.FileAppender+MinimalLock" /&gt;来使用最小锁定模型（minim...&nbsp;&nbsp;<a href='http://www.cnitblog.com/seeyeah/archive/2008/10/16/50334.html'>阅读全文</a><img src ="http://www.cnitblog.com/seeyeah/aggbug/50334.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-10-16 22:47 <a href="http://www.cnitblog.com/seeyeah/archive/2008/10/16/50334.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4net.Layout.PatternLayout用法</title><link>http://www.cnitblog.com/seeyeah/archive/2008/10/15/50291.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 15 Oct 2008 14:07:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/10/15/50291.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/50291.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/10/15/50291.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/50291.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/50291.html</trackback:ping><description><![CDATA[摘至：<a href="http://www.cnblogs.com/xiaolang3/archive/2006/09/25/514424.html">http://www.cnblogs.com/xiaolang3/archive/2006/09/25/514424.html</a><br>
<hr>
<table cellSpacing=0 cellPadding=0 width="90%" border=1>
    <tbody>
        <tr>
            <td vAlign=bottom width="22%">
            <p><strong><span>轉換字符</span></strong><strong></strong></p>
            </td>
            <td vAlign=bottom width="77%">
            <p><strong><span>效果</span></strong><strong></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>a</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>appdomain</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>appdomain</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>Used to output the friendly name of the AppDomain where the logging event was generated. </span></p>
            <p><span>用於輸出日誌事件發生的</span><span>AppDomain</span><span>的一個友好的名字</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>c</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><strong><span>logger</span></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>C</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><strong><span>type</span></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>class</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><strong><span>type</span></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>d</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><strong><span>date</span></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>date</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出日誌事件在當前時區中的日期</span><span>.</span><span>若要輸出通用時間</span><span>,</span><span>請使用</span><span>%utcdate</span><span>模式</span><span>.</span><span>日期轉換指定符後可以跟隨一對閉合的花括號</span><span>, </span><span>花括號裡面為日期格式指定符</span><span>.</span><span>例如</span><span>:<strong> %date{HH:mm:ss,fff}</strong></span><strong><span>或</span></strong><strong><span>%date{dd MMM yyyy HH:mm:ss,fff},</span></strong><span>若沒有指定任何格式</span><span>,</span><span>默認為</span><span>ISO8601</span><span>(<a href="file://Terry221/d$/桌面彙總資料/下載/Log4Net/incubating-log4net-1.2.9-beta/doc/release/sdk/log4net.DateFormatter.Iso8601DateFormatter.html"><u><font color=#0000ff>Iso8601DateFormatter</font></u></a>)<span>.</span></span></p>
            <p><span>格式指定符和</span><span>TOString</span><span>的語法一樣</span><span>.</span></p>
            <p><span>為了達到較好的效果</span><span>,</span><span>建議使用</span><span>log4net</span><span>日期格式化器</span><span>.</span><span>他們可以使用以下一個字符串</span><span>&#8221;ABSOLUTE&#8221;,&#8221;DATE&#8221;,&#8221;ISO<st1:chmetcnv w:st="on" UnitName="&#8221;" SourceValue="8601" HasSpace="False" Negative="False" NumberType="1" TCSC="0">8601&#8221;</st1:chmetcnv></span><span>來分別指定</span><span><a href="file://Terry221/d$/桌面彙總資料/下載/Log4Net/incubating-log4net-1.2.9-beta/doc/release/sdk/log4net.DateFormatter.AbsoluteTimeDateFormatter.html"><u><font color=#0000ff>AbsoluteTimeDateFormatter</font></u></a>, <a href="file://Terry221/d$/桌面彙總資料/下載/Log4Net/incubating-log4net-1.2.9-beta/doc/release/sdk/log4net.DateFormatter.DateTimeDateFormatter.html"><u><font color=#0000ff>DateTimeDateFormatter</font></u></a></span><span>和</span><strong><span>Iso8601DateFormatter.</span></strong><strong><span>例如</span></strong><strong><span>: %date{ISO8601}</span></strong><span> or <strong>%date{ABSOLUTE}</strong>.</span></p>
            <p><span>這些專用的日期格式化器效果比</span><span>ToString</span><span>好很多</span><span>. </span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>exception</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出連同日誌信息一起傳入的異常</span><span>.</span></p>
            <p><span>如果一個異常對象被儲存在日誌記錄事件中</span><span>,</span><span>他將會被帶有</span><span>trailing newline</span><span>的模式輸出</span><span>.</span><span>否則</span><span>,</span><span>不會</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>F</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>file</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>file</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出引發日誌記錄請求的文件名稱</span><span>.</span></p>
            <p><span>例如</span><span>: c:\inetpub\wwwroot\logtest\webform1.aspx.cs</span></p>
            <p><strong><span>警告</span></strong><strong><span>:</span></strong><span>產生呼叫者的位置信息相當慢</span><span>.</span><span>盡量避免使用</span><span>,</span><span>除非執行速度不是問題</span><span>. </span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>identity</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出當前用戶的用戶名</span><span>(Principal.Identity.Name).</span></p>
            <p><strong><span>警告</span></strong><strong><span>:</span></strong><span>產生呼叫者的位置信息相當慢</span><span>.</span><span>盡量避免使用</span><span>,</span><span>除非執行速度不是問題</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>l</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><strong><span>location</span></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>L</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><strong><span>line</span></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>location</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出產生日誌記錄事件的呼叫者的位置信息</span><span>.</span></p>
            <p><span>此位置信息依賴於</span><span>CLI</span><span>的實現</span><span>,</span><span>但是他通常為命名空間限制的方法且後用跟用圓括號括起來的呼叫者文件名和行號</span><span>.</span></p>
            <p><span>例如</span><span>:LogTest.WebForm1.Button3_Click(c:\inetpub\wwwroot\logtest\webform1.aspx.cs:93)</span></p>
            <p><span>位置信息非常有用</span><span>.</span><span>然而</span><span>,</span><span>他的產生相當慢</span><span>. </span><span>盡量避免使用</span><span>,</span><span>除非執行速度不是問題</span><span>. </span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>level</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸入記錄事件的等級</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>line</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出引發日誌記錄請求的行號</span><span>.</span></p>
            <p><strong><span>警告</span></strong><strong><span>:</span></strong><span>產生呼叫者的位置信息相當慢</span><span>.</span><span>盡量避免使用</span><span>,</span><span>除非執行速度不是問題</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>logger</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出日誌記錄事件的日誌名字</span><span>.</span><span>這個日誌轉換符後面可以跟精度</span><span>,</span><span>精度是十進制常量</span><span>,</span><span>用花括號括起來</span><span>.</span><span>如果指定了精度符</span><span>,</span><span>則只會輸出從右向左的相應數目的名字</span><span>,</span><span>默認為輸入全部</span><span>.</span></p>
            <p><span>如下</span><span>:</span><span>日誌記錄器的名字為</span><span>&#8221;a.b.c&#8221;,<strong> %logger{2}</strong></span><span>將會輸出</span><span>&#8221;b.c&#8221;</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>m</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><strong><span>message</span></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>M</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>method</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>message</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出應用程式提供給日誌記錄事件的信息</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>mdc</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>MDC(</span><span>舊名</span><span>: ThreadContext.Properties)</span><span>是聯合事件屬性的一部份</span><span>.</span><span>這個模式支持兼容性</span><span>,</span><span>但是等同於</span><strong><span>property</span></strong><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>method</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出引發日誌記錄請求的方法的名字</span><span>.</span></p>
            <p><strong><span>警告</span></strong><strong><span>:</span></strong><span>產生呼叫者的位置信息相當慢</span><span>.</span><span>盡量避免使用</span><span>,</span><span>除非執行速度不是問題</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>n</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>newline</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>newline</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>換行</span><span>,</span><span>等同於</span><span>&#8221;\n&#8221;</span><span>或</span><span>&#8221;\r\n&#8221; </span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>p</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>level</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>P</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>property</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>properties</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>property</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>property</span></p>
            </td>
            <td vAlign=top width="77%">
            <p>&nbsp;</p>
            <p><span>用於輸出一個事件的指定的屬性</span><span>.</span><span>屬性名字要以花括號括起來並且直接放到</span><span>property</span><span>後面</span><span>.</span><span>例如</span><span>:%property{user}.</span><span>日誌中的每一個屬性指都需要單獨指定</span><span>.Properties</span><span>是日誌記錄器或追加器添加到事件中的</span><span>.</span><span>默認屬性為</span><span>log4net:HostName</span><span>,</span><span>它是引發產生記錄事件的機器名字</span><span>. </span></p>
            <p><span>若果沒有指定關鍵字</span><span>,</span><span>比如</span><span>: <strong>%property</strong> ,</span><span>將會將鍵值以逗號分格列表</span><span> </span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>r</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>timestamp</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>t</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><strong><span>thread</span></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>timestamp</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出從程式啟動到日誌記錄事件建立的時間</span><span>,</span><span>以毫秒記</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>thread</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出引發日誌記錄事件的線程的名字</span><span>,</span><span>若無線程名</span><span>,</span><span>則用線程號</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>type</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>所用同</span><span>logger</span></p>
            <p><strong><span>警告</span></strong><strong><span>:</span></strong><span>產生呼叫者的位置信息相當慢</span><span>.</span><span>盡量避免使用</span><span>,</span><span>除非執行速度不是問題</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>u</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>identity</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>username</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>用於輸出當前用戶的</span><span>WindowsIdentity</span></p>
            <p><strong><span>警告</span></strong><strong><span>:</span></strong><span>產生呼叫者的位置信息相當慢</span><span>.</span><span>盡量避免使用</span><span>,</span><span>除非執行速度不是問題</span><span>. </span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>utcdate</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>使用同</span><span>date </span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>w</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>username</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>x</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>ndc</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>X</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>等同於</span><span> <strong><span>mdc</span></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>%</span></p>
            </td>
            <td vAlign=top width="77%">
            <p><span>%%</span><span>輸出一個</span><span>%</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span>-</span><span>左對齊<span>,</span>若不足指定的長度<span>,</span>則右側補足缺少的空格數<span>.</span></span></p>
<p><span>沒有任何符合<span>,</span>右對齊<span>, </span>若不足指定的長度<span>,</span>則左側補足缺少的空格數<span>.</span></span></p>
<p><span>.</span><span>最大長度<span>,</span>若超過指定的最大長度<span>,</span>則從右側進行截斷<span>.</span></span></p>
<table cellSpacing=0 cellPadding=0 width="90%" border=1>
    <tbody>
        <tr>
            <td vAlign=bottom>
            <p><strong><span>格式修飾符</span></strong><strong></strong></p>
            </td>
            <td vAlign=bottom width="9%">
            <p><strong><span>左對齊</span></strong><strong></strong></p>
            </td>
            <td vAlign=bottom width="12%">
            <p><strong><span>最小長度</span></strong><strong></strong></p>
            </td>
            <td vAlign=bottom width="16%">
            <p><strong><span>最大長度</span></strong><strong></strong></p>
            </td>
            <td vAlign=bottom width="43%">
            <p><strong><span>說明</span></strong><strong></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>%20logger</span></p>
            </td>
            <td vAlign=top width="9%">
            <p><span>false</span></p>
            </td>
            <td vAlign=top width="12%">
            <p><span>20</span></p>
            </td>
            <td vAlign=top width="16%">
            <p><span>none</span></p>
            </td>
            <td vAlign=top width="43%">
            <p><span>若長度小於</span><span>20,</span><span>則左側補足空格</span><span>. </span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>%-20logger</span></p>
            </td>
            <td vAlign=top width="9%">
            <p><span>true</span></p>
            </td>
            <td vAlign=top width="12%">
            <p><span>20</span></p>
            </td>
            <td vAlign=top width="16%">
            <p><span>none</span></p>
            </td>
            <td vAlign=top width="43%">
            <p><span>若長度小於</span><span>20,</span><span>則右側補足空格</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>%.30logger</span></p>
            </td>
            <td vAlign=top width="9%">
            <p><span>NA</span></p>
            </td>
            <td vAlign=top width="12%">
            <p><span>none</span></p>
            </td>
            <td vAlign=top width="16%">
            <p><span>30</span></p>
            </td>
            <td vAlign=top width="43%">
            <p><span>若長度大於</span><span>30,</span><span>則從器始位置截斷</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>%20.30logger</span></p>
            </td>
            <td vAlign=top width="9%">
            <p><span>false</span></p>
            </td>
            <td vAlign=top width="12%">
            <p><span>20</span></p>
            </td>
            <td vAlign=top width="16%">
            <p><span>30</span></p>
            </td>
            <td vAlign=top width="43%">
            <p><span>若長度小於</span><span>20,</span><span>則左側補足空格</span><span>,</span><span>然而若長度大於</span><span>30,</span><span>則從起始位置截斷</span><span>.</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top>
            <p><span>%-20.30logger</span></p>
            </td>
            <td vAlign=top width="9%">
            <p><span>true</span></p>
            </td>
            <td vAlign=top width="12%">
            <p><span>20</span></p>
            </td>
            <td vAlign=top width="16%">
            <p><span>30</span></p>
            </td>
            <td vAlign=top width="43%">
            <p><span>若長度小於</span><span>20,</span><span>則右側補足空格</span><span>,</span><span>然而若長度大於</span><span>30,</span><span>則從起始位置截斷</span><span>.</span></p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/50291.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-10-15 22:07 <a href="http://www.cnitblog.com/seeyeah/archive/2008/10/15/50291.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.Net Remoting Reference</title><link>http://www.cnitblog.com/seeyeah/archive/2008/07/15/46760.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Tue, 15 Jul 2008 15:06:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/07/15/46760.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/46760.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/07/15/46760.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/46760.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/46760.html</trackback:ping><description><![CDATA[<p><a class=headermaintitle id=Header1_HeaderTitle href="http://www.cnblogs.com/wayfarer/"><u><font color=#0000ff>张逸:晴窗笔记</font></u></a><br><br><a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/wayfarer/archive/2004/07/30/28723.html"><u><font color=#800080>Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇 </font></u></a><br><br><a id=viewpost1_TitleUrl href="http://www.cnblogs.com/wayfarer/archive/2004/08/05/30437.html"><font color=#000080><u>Microsoft .Net Remoting系列专题之二：Marshal、Disconnect与生命周期以及跟踪服务</u></font></a></p>
<p><a id=viewpost1_TitleUrl href="http://www.cnblogs.com/wayfarer/articles/75213.html"><font color=#000080><u>Microsoft .Net Remoting系列专题之三：Remoting事件处理全接触</u></font></a><br><br>
<hr>
<p><a class=HeaderMainTitle id=Header1_HeaderTitle href="http://www.cnblogs.com/dahuaidan410/"><u><font color=#0000ff>大坏蛋</font></u></a><br><br><a id=CategoryEntryList1_EntryStoryList_Entries_ctl01_TitleUrl href="http://www.cnblogs.com/dahuaidan410/archive/2004/08/09/31658.html"><u><font color=#0000ff>.NET Remoting中的事件处理(.NET Framework 2.0) </font></u></a><br><br><a id=CategoryEntryList1_EntryStoryList_Entries_ctl00_TitleUrl href="http://www.cnblogs.com/dahuaidan410/archive/2004/09/10/41726.html"><u><font color=#0000ff>.NET Remoting的新特性-IpcChannel(.NET Framework 2.0) </font></u></a><br><br>
<hr>
<br><a href="http://www.cnblogs.com/zhenyulu/"><font color=#0000ff><u>吕震宇</u></font></a><font color=#0000ff><u> </u></font><br><br><a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/zhenyulu/articles/29357.html"><u><font color=#800080>利用Event松耦合远程对象与远程系统</font></u></a>
<p>&nbsp;</p>
<hr>
<br><a class=HeaderMainTitle id=Header1_HeaderTitle href="http://www.cnblogs.com/Ansel/"><u><font color=#0000ff>Ansel's Blog</font></u></a><br><br><a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/Ansel/archive/2005/04/19/140595.html"><u><font color=#800080>WebService VS .NET Remoting</font></u></a> <br><br>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/46760.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-07-15 23:06 <a href="http://www.cnitblog.com/seeyeah/archive/2008/07/15/46760.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A Quick Start Guide to iBATIS DataMapper</title><link>http://www.cnitblog.com/seeyeah/archive/2008/07/10/46575.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Thu, 10 Jul 2008 15:06:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/07/10/46575.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/46575.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/07/10/46575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/46575.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/46575.html</trackback:ping><description><![CDATA[<h3><a name=QuickStartGuide-Overview></a>Overview</h3>
<p>iBATIS DataMapper is a Java/.NET framework that will help you design and implement better persistence layers for your Java/.NET applications. iBATIS couples objects with stored procedures or SQL statements using a XML descriptor. Simplicity is the biggest advantage of the iBATIS Data Mapper over object relational mapping tools. </p>
<p>To use iBATIS Data Mapper you rely on your own objects, XML, and SQL. There is little to learn that you don't already know. With iBATIS Data Mapper you have the full power of both SQL and stored procedures at your fingertips.</p>
<h3><a name=QuickStartGuide-Oursampleproject></a>Our sample project</h3>
<p>This sample takes an "over-the-shoulder" Cookbook approach. We'll define a simple data access problem and use iBATIS to solve it for us. Let's say our client has a database and one of the tables in the database is a list of people. The client tells us:</p>
<p>"We would like to use a web application to display the people in this table and to add, edit, and delete individual records."</p>
<p>Not a complicated story, but it will cover the CRUD most developers want to learn first. <img class=emoticon height=20 alt="" src="http://opensource.atlassian.com/confluence/oss/images/icons/emoticons/smile.gif" width=20 align=absMiddle border=0> </p>
<h3><a name=QuickStartGuide-Step1%3ATheSQL></a>Step 1 : The SQL</h3>
<p>Let's start with the people table client mentioned. Since we're keeping it simple, we'll say it's a table in an Access database. The table definition is shown as </p>
<table class=confluenceTable>
    <tbody>
        <tr>
            <th class=confluenceTh>Name</th>
            <th class=confluenceTh>Type</th>
            <th class=confluenceTh>Size</th>
        </tr>
        <tr>
            <td class=confluenceTd>PER_ID</td>
            <td class=confluenceTd>Long Integer</td>
            <td class=confluenceTd>4</td>
        </tr>
        <tr>
            <td class=confluenceTd>PER_FIRST_NAME</td>
            <td class=confluenceTd>Text</td>
            <td class=confluenceTd>40</td>
        </tr>
        <tr>
            <td class=confluenceTd>PER_LAST_NAME </td>
            <td class=confluenceTd>Text</td>
            <td class=confluenceTd>40</td>
        </tr>
        <tr>
            <td class=confluenceTd>PER_BIRTH_DATE </td>
            <td class=confluenceTd>Date/Time</td>
            <td class=confluenceTd>8</td>
        </tr>
        <tr>
            <td class=confluenceTd>PER_WEIGHT_KG </td>
            <td class=confluenceTd>Double</td>
            <td class=confluenceTd>8</td>
        </tr>
        <tr>
            <td class=confluenceTd>PER_HEIGHT_M </td>
            <td class=confluenceTd>Double</td>
            <td class=confluenceTd>8</td>
        </tr>
    </tbody>
</table>
<h3><a name=QuickStartGuide-Step2%3AThe.NETClass></a>Step 2 :The.NET Class</h3>
<div class=code style="BORDER-TOP-STYLE: dashed; BORDER-RIGHT-STYLE: dashed; BORDER-LEFT-STYLE: dashed; BORDER-BOTTOM-STYLE: dashed">
<div class=codeHeader style="BORDER-BOTTOM-STYLE: dashed"><strong>Person.cs</strong></div>
<div class=codeContent>
<pre class=code-java>using <span class=code-object>System</span>;
namespace iBatisTutorial.Model
{
<span class=code-keyword>public</span> class Person
{
<span class=code-keyword>private</span> <span class=code-object>int</span> _id;
<span class=code-keyword>private</span> string _firstName;
<span class=code-keyword>private</span> string _lastName;
<span class=code-keyword>private</span> DateTime _birthDate;
<span class=code-keyword>private</span> <span class=code-object>double</span> _weightInKilograms;
<span class=code-keyword>private</span> <span class=code-object>double</span> _heightInMeters;
<span class=code-keyword>public</span> <span class=code-object>int</span> Id
{
get{ <span class=code-keyword>return</span> _id; }
set{ _id = value; }
}
<span class=code-comment>// Other <span class=code-keyword>public</span> properties <span class=code-keyword>for</span> the <span class=code-keyword>private</span> fields ...
</span>
}
}</pre>
</div>
</div>
<h3><a name=QuickStartGuide-Step3%3ATheNunittest></a>Step 3 :The Nunit test</h3>
<p>The first thing our story says is that client would like to display a list of people. </p>
<div class=code style="BORDER-TOP-STYLE: dashed; BORDER-RIGHT-STYLE: dashed; BORDER-LEFT-STYLE: dashed; BORDER-BOTTOM-STYLE: dashed">
<div class=codeHeader style="BORDER-BOTTOM-STYLE: dashed"><strong>PersonTest.cs</strong></div>
<div class=codeContent>
<pre class=code-java>using <span class=code-object>System</span>.Collections;
using IBatisNet.DataMapper;
using NUnit.Framework;
namespace iBatisTutorial.Model
{
[TestFixture]
<span class=code-keyword>public</span> class PersonTest
{
[Test]
<span class=code-keyword>public</span> void PersonList ()
{
<span class=code-comment>// <span class=code-keyword>try</span> it
</span>    IList people = Mapper.Instance().QueryForList(<span class=code-quote>"SelectAll"</span>,<span class=code-keyword>null</span>);
<span class=code-comment>// test it
</span>    Assert.IsNotNull(people,<span class=code-quote>"Person list not returned"</span>);
Assert.IsTrue(people.Count&gt;0,<span class=code-quote>"Person list is empty"</span>);
Person person = (Person) people[0];
Assert.IsNotNull(person,<span class=code-quote>"Person not returned"</span>);
}
}
}</pre>
</div>
</div>
<p>OK, that was fun! The Assert class is built into NUnit, so to compile, we just need the Mapper object and QueryForList method. The Mapper is built into the iBATIS framework, so we don't need to write that either. The iBATIS <strong>QueryForList</strong> method executes our SQL statement (or stored procedure) and returns the result as a list. <br>Each row in the result becomes an entry in the list. Along with QueryForList, there is also Delete, Insert, Select, QueryForObject, and a couple of other methods in the iBATIS API. (See the Developers Guide for details.)</p>
<p>Looking at <strong>PersonTest</strong> class, we see that the <strong>QueryForList</strong> method takes the name of the statement we want to run and any runtime values the statement may need. Since a "SelectAll" statement wouldn't need any runtime values, we pass null in our test.</p>
<p>OK. Easy enough. But where does iBATIS get the "<strong>SelectAll</strong>" statement? </p>
<p>Some systems try to generate SQL statements for you, but iBATIS specializes in data mapping, not code generation. It's our job (or the job of our database administrator) to craft the SQL or provide a stored procedure. We then describe the statement in an XML element, like the one shown below.</p>
<h3><a name=QuickStartGuide-Step4%3AThemappingfile></a>Step 4 :The mapping file</h3>
<div class=code style="BORDER-TOP-STYLE: dashed; BORDER-RIGHT-STYLE: dashed; BORDER-LEFT-STYLE: dashed; BORDER-BOTTOM-STYLE: dashed">
<div class=codeHeader style="BORDER-BOTTOM-STYLE: dashed"><strong>Person.xml</strong></div>
<div class=codeContent>
<pre class=code-xml><span class=code-tag>&lt;alias&gt;</span>
<span class=code-tag>&lt;typeAlias alias=<span class=code-quote>"Person"</span> type=<span class=code-quote>"iBatisTutorial.Model.Person, iBatisTutorial.Model"</span> /&gt;</span>
<span class=code-tag>&lt;/alias&gt;</span>
<span class=code-tag>&lt;resultMap id=<span class=code-quote>"SelectAllResult"</span> class=<span class=code-quote>"Person"</span>&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"Id"</span> column=<span class=code-quote>"PER_ID"</span> /&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"FirstName"</span> column=<span class=code-quote>"PER_FIRST_NAME"</span> /&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"LastName"</span> column=<span class=code-quote>"PER_LAST_NAME"</span> /&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"BirthDate"</span> column=<span class=code-quote>"PER_BIRTH_DATE"</span> /&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"WeightInKilograms"</span> column=<span class=code-quote>"PER_WEIGHT_KG"</span> /&gt;</span>
<span class=code-tag>&lt;result property=<span class=code-quote>"HeightInMeters"</span> column=<span class=code-quote>"PER_HEIGHT_M"</span> /&gt;</span>
<span class=code-tag>&lt;/resultMap&gt;</span>
<span class=code-tag>&lt;select id=<span class=code-quote>"SelectAll"</span> resultMap=<span class=code-quote>"SelectAllResult"</span>&gt;</span>
select
PER_ID,
PER_FIRST_NAME,
PER_LAST_NAME,
PER_BIRTH_DATE,
PER_WEIGHT_KG,
PER_HEIGHT_M
from PERSON
<span class=code-tag>&lt;/select&gt;</span></pre>
</div>
</div>
<p>The iBATIS mapping documents can hold several sets of related elements, like those shown. We can also have as many mapping documents as we need. Having multiple mapping documents is handy when several developers are working on the project at once.</p>
<p>So, the framework gets the SQL code for the query from the mapping, and plugs it into a prepared statement. But, how does iBATIS know where to find the table's datasource?</p>
<p>Surprise! More XML! You can define a configuration file for each datasource your application uses. The example below shows a configuration file for our Access database.</p>
<h3><a name=QuickStartGuide-Step5%3ATheconfigurationfile></a>Step 5 :The configuration file</h3>
<div class=code style="BORDER-TOP-STYLE: dashed; BORDER-RIGHT-STYLE: dashed; BORDER-LEFT-STYLE: dashed; BORDER-BOTTOM-STYLE: dashed">
<div class=codeHeader style="BORDER-BOTTOM-STYLE: dashed"><strong>SqlMap.Config - A configuration file for our Access database</strong></div>
<div class=codeContent>
<pre class=code-xml><span class=code-tag>&lt;?xml version=<span class=code-quote>"1.0"</span> encoding=<span class=code-quote>"UTF-8"</span> ?&gt;</span>
&lt;sqlMapConfig
xmlns=<span class=code-quote>"http://ibatis.apache.org/dataMapper"</span>
<span class=code-keyword>xmlns:xsi</span>=<span class=code-quote>"http://www.w3.org/2001/XMLSchema-instance"</span> &gt;
<span class=code-tag>&lt;database&gt;</span>
<span class=code-tag>&lt;provider name=<span class=code-quote>"OleDb1.1"</span>/&gt;</span>
&lt;dataSource name=<span class=code-quote>"iBatisTutorial"</span>
connectionString=<span class=code-quote>"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=./Resources/iBatisTutorial.mdb"</span>/&gt;
<span class=code-tag>&lt;/database&gt;</span>
<span class=code-tag>&lt;sqlMaps&gt;</span>
<span class=code-tag>&lt;sqlMap resource=<span class=code-quote>"Resources/Person.xml"</span> /&gt;</span>
<span class=code-tag>&lt;/sqlMaps&gt;</span>
<span class=code-tag>&lt;/sqlMapConfig&gt;</span></pre>
</div>
</div>
<p>Of course, besides Access, other ADO.NET providers are supported, including SqlServer, Oracle, MySQL, PostgreSQL, DB2 and generic OLEDB, ODBC providers. (See the Developers Guide for details.)</p>
<p>The last part of the configuration file ("sqlMaps") is where we list our mapping documents, like the one shown back in Step 4. We can list as many documents as we need here, and they will all be read when the configuration is parsed.</p>
<p>OK, so how does the configuration get parsed?</p>
<p>Look back at PersonTest class in step 3. The heart of the code is the call to the "Mapper" object (under the remark "try it"). The Mapper object is a singleton. The first time it's called, it reads in the configuration documents to create the Mapper object. On subsequent calls, it reuses the Mapper object, so that the configuration is re-read only if the file changes.</p>
<p>The framework comes bundled with a default Mapper class. If you want to use a different name for the configuration file, or need to use more than one database, you can also use your own class, by copying and modifying the standard version.</p>
<p>The following example shows the code for the standard Mapper class that comes with the framework.</p>
<div class=code style="BORDER-TOP-STYLE: dashed; BORDER-RIGHT-STYLE: dashed; BORDER-LEFT-STYLE: dashed; BORDER-BOTTOM-STYLE: dashed">
<div class=codeHeader style="BORDER-BOTTOM-STYLE: dashed"><strong>Mapper.cs</strong></div>
<div class=codeContent>
<pre class=code-java>using IBatisNet.Common.Utilities;
using IBatisNet.DataMapper;
namespace IBatisNet.DataMapper
{
<span class=code-keyword>public</span> class Mapper
{
<span class=code-keyword>private</span> <span class=code-keyword>static</span> <span class=code-keyword>volatile</span> SqlMapper _mapper = <span class=code-keyword>null</span>;
<span class=code-keyword>protected</span> <span class=code-keyword>static</span> void Configure (object obj)
{
_mapper = (SqlMapper) obj;
}
<span class=code-keyword>protected</span> <span class=code-keyword>static</span> void InitMapper()
{
ConfigureHandler handler = <span class=code-keyword>new</span> ConfigureHandler (Configure);
_mapper = SqlMapper.ConfigureAndWatch (handler);
}
<span class=code-keyword>public</span> <span class=code-keyword>static</span> SqlMapper Instance()
{
<span class=code-keyword>if</span> (_mapper == <span class=code-keyword>null</span>)
{
lock (typeof (SqlMapper))
{
<span class=code-keyword>if</span> (_mapper == <span class=code-keyword>null</span>) <span class=code-comment>// <span class=code-object>double</span>-check
</span>      InitMapper();
}
}
<span class=code-keyword>return</span> _mapper;
}
<span class=code-keyword>public</span> <span class=code-keyword>static</span> SqlMapper Get()
{
<span class=code-keyword>return</span> Instance();
}
}
}</pre>
</div>
</div>
<p>You can access as many different database configurations as you need, just by setting up additional Mapper classes. Each Mapper configuration is a facade for a database. As far as our application knows, the "Mapper" <strong>is</strong> the database. Behind the Mapper facade, you can change the location of the database, or switch between SQL statements and stored procedures, with zero-changes to your application code.</p>
<h3><a name=QuickStartGuide-Step5%3ARunningthetest></a>Step 5 :Running the test</h3>
<p>If we put this all together into a solution, we can "green bar" our test, as shown by figure. </p>
<p><img src="http://opensource.atlassian.com/confluence/oss/download/attachments/495/figure01.gif" align=absMiddle border=0> </p>
<!--
<rdf:rdf xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:description
rdf:about="http://opensource.atlassian.com/confluence/oss/display/IBATIS/Quick+Start+Guide"
dc:identifier="http://opensource.atlassian.com/confluence/oss/display/IBATIS/Quick+Start+Guide"
dc:title="Quick Start Guide"
trackback:ping="http://opensource.atlassian.com/confluence/oss/rpc/trackback/495"/>
</rdf:rdf>
--><!--
Root decorator: all decisions about how a page is to be decorated via the
inline decoration begins here.
--><!--
Switch based upon the context. However, for now, just delegate to a decorator
identified directly by the context.
-->
<img src ="http://www.cnitblog.com/seeyeah/aggbug/46575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-07-10 23:06 <a href="http://www.cnitblog.com/seeyeah/archive/2008/07/10/46575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ibatis的优缺点及可行性分析</title><link>http://www.cnitblog.com/seeyeah/archive/2008/07/09/46522.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 09 Jul 2008 14:31:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/07/09/46522.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/46522.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/07/09/46522.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/46522.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/46522.html</trackback:ping><description><![CDATA[<p>摘至：<a href="http://selfishman.bokee.com/3901159.html">http://selfishman.bokee.com/3901159.html</a><br>
<hr>
<br>1.优点
<p>&#160;</p>
<p>简单：<br>&nbsp;易于学习，易于使用，通过文档和源代码，可以比较完全的掌握它的设计思路和实现。</p>
<p>实用：<br>&nbsp;提供了数据映射功能，提供了对底层数据访问的封装（例如ado.net），提供了DAO框架，可以使我们更容易的开发和配置我们的DAL层。<br>&nbsp;<br>灵活：<br>&nbsp;通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能，或许更多。<br>&nbsp;<br>功能完整：<br>&nbsp;提供了连接管理，缓存支持，线程支持，（分布式）事物管理，通过配置作关系对象映射等数据访问层需要解决的问题。提供了DAO支持，并在DAO框架中封装了ADO.NET，NHibernate和DataMapper。<br>&nbsp;<br>增强系统的可维护性： <br>&nbsp;通过提供DAL层，将业务逻辑和数据访问逻辑分离，使系统的设计更清晰，更易维护，更易单元测试。sql和代码的分离，提高了可维护性。<br>&nbsp;<br>2.缺点<br>滞后性：<br>&nbsp;还没有明确对.NET2.0的支持。最新版本在2.0下编译可以，但有些单元测试不能通过。<br>不成熟，工程实践较少： <br>&nbsp;IbatisNet在实际项目中的使用较少。 只是理论上可行.<br>半ORM，工具支持较少： <br>&nbsp;需要我们自己写sql，并且.NET下还未发现可以自动生成业务层类和配置文件的工具，这点和NHibernate不一样，NHibernate会为我们的数据库直接产生sql，并有一些辅助工具。因此使用Ibatis比NHibernate要多做一些工作。<br>&nbsp;<br>3.可行性<br>&nbsp;&nbsp;&nbsp; 没有最好的框架，只有最适合的框架。 存在的便是合理的，它存在就说明有它存在的道理。但它未必为我们存在。所以选择一个框架最主要的是看它对你有没有意义，意义有多大，是不是比其他框架带给你的好处要多。没有绝对的优点也没有绝对的缺点，重要的是看在什么情况下讨论。<br>&nbsp;&nbsp;&nbsp; 上面说了部分的Ibatis的优点和部分缺点。这些优点从理论上证明Ibatis对任何数据持久层都合适，但未必是最好的选择。下面对上面的优缺点分别从两方面讨论。<br>&nbsp;<br>简单：<br>&nbsp;&nbsp;&nbsp; 我们都喜欢简单，简单意味着学习成本低，使用中出错的可能性低。同时，简单的东西一般来说功能不够强大。反过来，复杂的东西学习成本高，用起来不方便，并且团队没有很强的技术实力，一般不要使用。<br>实用：<br>&nbsp;&nbsp;&nbsp; 解决了项目中需要解决的问题，这是任何实际工程中采用的框架和工具都应具有的性质，否则就不要拿到实际项目中来。<br>灵活：<br>&nbsp;&nbsp;&nbsp; 灵活有两层意思，一种是简单易扩展，另一种是功能强大提供了很多选项。Ibatis属于前者，Hibernate属于后者。两者各有优缺点。<br>功能完整：<br>&nbsp;&nbsp;&nbsp; Ibatis的功能完整也是相对的，比我们自己开发的框架应该完整，但对比其他框架肯定也有一些解决不了的问题。<br>增强系统的可维护性：<br>&nbsp;&nbsp;&nbsp; 利用Ibatis可以做到sql和代码分离，可以设计出一个清晰的数据访问层（DAL）。但项目架构是否科学合理，是否以维护，关键不在Ibatis，因为它只是一个数据层框架。但是我们也不得不清楚，要想发挥Ibatis的优势，我们需要做一些额外工作，比如最好设计DAO接口，需要将业务层实体和对实体的访问放在不同的工程中，同时需要维护xml配置文件。<br>滞后性：<br>&nbsp;&nbsp;&nbsp; Ibatis组现在还没有提到要支持.NET2.0，很多人在.NET2.0下使用Ibatis都出现了问题。所以如果要使用.NET2.0开发，IBatis不是一个好选择，还需要等待。<br>不成熟：<br>&nbsp;&nbsp;&nbsp; 开源的东西很难说成熟，但一般比我们自己写的框架要成熟。由于我们可以拿到他的源代码，所以关键在于我们能否驾驭它。<br>半ORM，工具支持少：<br>&nbsp;&nbsp;&nbsp; 这注定了Ibatis不能从本质上提升开发效率，我们需要自己写sql，写实体类，写配置文件。但这也是它优越的地方，它没有为我们做的他多，所以我们就有更多的施展空间。而且它非常适合那些并不能完全控制数据库的系统和需要利用数据库本身提供的高级特性的统计查询系统的开发。<br>&nbsp;&nbsp;&nbsp; 使用Ibatis需要自己写sql，由于我们的sql不可能完全符合sql标准，比起NHibernate产生的sql来，可移植性差。不过由于我们更改数据库的可能性较小，对我们来说sql符合标准以便可以在迁移到不同服务器时代价最小并不是十分必要的。另一方面，NHibernate虽然可以屏蔽很多数据库间的不同，但是却很难利用某些数据库的高级特性，比如Oracle的分析统计函数。 <br>&nbsp;&nbsp;&nbsp;&nbsp; NHibernate不适合数据库模式不规范，约束不完整，需要大量复杂查询的系统，同时NHibernate的学习成本较高，完全掌握NHibernate也较困难，风险较大。<br>&nbsp;&nbsp;&nbsp; 自己写框架未必比Ibatis的好，稳定，强大和可扩展。而且自己开发框架也需要较大的工作量。<br>&nbsp;&nbsp;&nbsp; 如果使用DotNet并且要选一个数据层框架，而系统中有相当一部分较复杂的sql，或数据库设计不合理，脏数据多，对性能和资源要求严格，Ibatis是一个比较不错的选择。他的那些缺点并不是致命的，而且也是有一些解决方案的。尤其是，当选用了Ibatis的DataAccess作为DAO框架时，我们可以同时使用NHibernate，ADO.NET和DataMapper（IbatisNet的核心组件），那样将会使风险降到最低，并且整个系统的框架比较合理。<br>&nbsp;另外，利用Ibatis可以统一编码风格，节约开发成本，大家不会再把精力浪费到分页&nbsp; 连接池 主键生成等地方了,可以集中精力进行业务组件的编写。&nbsp; </p>
<p><br>综上:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 很多时候我们要在是自己开发框架和选用第三方框架和选用什么样的框架问题上进行综合考虑。考虑的标准当然是项目的当前情况和我们希望达到目的的一个平衡。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; Ibatis只是封装了数据访问层，替我们做了部分的对象关系映射。但我们的代价是必须要写xml配置文件，相对于Hibernate我们还要写很多sql。Hibernate通过工具直接从数据库模式生成实体类和基本的配置文件，而且大部分情况下不需要我们写sql，会较大的提升开发效率。但这些也有很多的局限性，尤其是对环境的要求较高（数据库设计，对象设计，团队的协作等）。<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; 个人感觉Ibatis对项目比较有意义的地方在于它小巧灵活，可扩展，封装了数据访问层（事务，缓存，异常，日志），并提供了DAO框架支持。<br>&nbsp;&nbsp;&nbsp; 利用Ibatis我们可以做到代码和sql的分离，只要sql能够解决的问题，Ibatis就能帮我们较容易的解决，同时也使我们的项目对某一框架的依赖性变小（因为Ibatis是非侵入性的）。这将极大的降低项目风险，减少解决复杂问题的时间，使项目的维护变得简单。<br>&nbsp;&nbsp; Ibatis对于应用的修改，调试，扩充和维护将会变得容易自然。修改时，我们主要修改的是代表模型的实体对象，xml配置文件中的sql，和/或配置文件的ResultMap（很多时候是不需要的）。同时，sql和代码分离，我们不用在代码的StringBuffer的append方法之间寻找需要修改的sql。配置文件中的sql便利了我们的调试和对sql的评审及以后的sql重用。<br>&nbsp;&nbsp;&nbsp; 利用一些框架在前期一般会拖慢开发效率。因为我们需要付出学习成本，很多时候，使用框架需要写很多配置文件，在使用不熟时开发速度较慢；同时利用框架往往使系统代码量增大，比如Model1和Model2模型，开发效率应该还是Model1快，四层的架构肯定比两层的代码量大。 但对于中后期开发和维护将会极大的提高效率。<br>&nbsp;&nbsp;&nbsp; 利用一些较完全的开发框架和代码生成工具，在前期会较大的提高开发效率，但在后期常常会拖慢进度，并有可能成为以后维护的梦魇。比如torque生成实体类和其对应的sql，虽大幅提高了效率，但修改负担较大。<br>&nbsp;&nbsp; 比较理想的开发方式是使用简单框架结合简单的代码生成工具。框架提供系统的基础服务，并规范开发。框架一方面提供了开发中某一方面的开发基础支持，比如数据访问层，事务，日志，公用类，异常等。另一方面，也为开发定义了模式，定义了系统的基本轮廓。同时，通过简单的代码生成工具生成部分低级的代码。比如通过工具从数据库模式生成实体类。这些类生成后我们可以自由修改。<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; Hibernate是十分强大，比较完善的ORM框架，不过这是它的优点也是它的缺点。 j2ee系统是否采用Hibernate3，是一个需要认真评估的问题。<br>&nbsp;&nbsp;&nbsp; 要想Hibernate工作的好，数据库的设计必须好。同时对于复杂的数据操作同时需要使用sql，Hibernate3对于直接使用sql的支持比Hibernate2要自然，这一点是可以接受的。<br>&nbsp;&nbsp;&nbsp; Hibernate比较复杂，功能强大而灵活，要用好Hibernate确实不是很简单，当然Spring框架提供了对Hibernate的封装，使Hibernate的使用变得简单了点。<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; 可以说Ibatis在任何系统里都适用，但未必是最好选择。不过Ibatis提供的思路是我们应该仔细考虑的。<br></p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/46522.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-07-09 22:31 <a href="http://www.cnitblog.com/seeyeah/archive/2008/07/09/46522.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原】补充who win in finally vs return? 【Reference Type Version】</title><link>http://www.cnitblog.com/seeyeah/archive/2008/06/14/45746.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Sat, 14 Jun 2008 03:36:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/06/14/45746.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/45746.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/06/14/45746.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/45746.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/45746.html</trackback:ping><description><![CDATA[在<a class=postTitle2 id=_b2a92868a5a_HomePageDays_DaysList_ctl00_DayItem_DayList_ctl02_TitleUrl href="http://www.cnitblog.com/seeyeah/archive/2008/06/13/45673.html"><u><font color=#800080>Quiz:who win in finally vs return? </font></u></a>中，我们看到的例子是以string作为返回值。<br><br>虽然string是引用类型，由于string的&#8220; immutability &#8221;特性，操作它的行为结果如同Value Type。<br><br>因此在上文中的结果只说明Value Type的显示结果，如果把返回值改为引用类型呢？<br><br>现有代码如下<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Program<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Main(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">[]&nbsp;args)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(Try2().Str);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;MyClass2&nbsp;Try2()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyClass2&nbsp;my2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;MyClass2();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my2.Str&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">try</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;my2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">finally</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my2.Str&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">final</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyClass2<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;Str&nbsp;{&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br>返回结果是&#8220;final&#8221;。<br><br>看看编译器把这段Try2这个方法转成了什么样的IL？<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">.method&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;hidebysig&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TryFinally.MyClass2&nbsp;Try2()&nbsp;cil&nbsp;managed<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.maxstack&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.locals&nbsp;init&nbsp;(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TryFinally.MyClass2&nbsp;my2,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">在方法里面有2个参数，1个是my2；第二个是IL生成的变量，用于返回结果</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TryFinally.MyClass2&nbsp;CS$</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">$</span><span style="COLOR: #000000">0000</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0000:&nbsp;nop&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0001:&nbsp;newobj&nbsp;instance&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;TryFinally.MyClass2::.ctor()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0006:&nbsp;stloc.</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0007:&nbsp;nop&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0008:&nbsp;ldloc.</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">把第一个参数my2推出栈顶</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0009:&nbsp;ldstr&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">try</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">加载"try"字符串</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_000e:&nbsp;callvirt&nbsp;instance&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;TryFinally.MyClass2::set_Str(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">调用my2的set_Str方法，即为Str属性赋值"try"。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0013:&nbsp;nop&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0014:&nbsp;ldloc.</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">把第一个参数my2推出栈顶</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0015:&nbsp;stloc.</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">把my2保存到CS$1$0000，即返回值</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0016:&nbsp;leave.s&nbsp;L_0027&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">转到&nbsp;L_0027指令。（但注意最后一句声明.try&nbsp;L_0007&nbsp;to&nbsp;L_0018&nbsp;finally&nbsp;handler&nbsp;L_0018&nbsp;to&nbsp;L_0027，因此在leave之前还需要执行L_0018&nbsp;to&nbsp;L_0027）</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0018:&nbsp;nop&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0019:&nbsp;ldloc.</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">把第一个参数my2推出栈顶</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_001a:&nbsp;ldstr&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">final</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">加载"final"字符串</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_001f:&nbsp;callvirt&nbsp;instance&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;TryFinally.MyClass2::set_Str(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">调用my2的set_Str方法，即为Str属性赋值"final"。这里虽然没有操作CS$1$0000，但引用类型嘛，CS$1$0000的值当然影响了。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0024:&nbsp;nop&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0025:&nbsp;nop&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0026:&nbsp;endfinally&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0027:&nbsp;nop&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">finally结束</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0028:&nbsp;ldloc.</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">最后把CS$1$0000返回。在这里CS$1$0000的Str已经是final了</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L_0029:&nbsp;ret&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000">&nbsp;L_0007&nbsp;to&nbsp;L_0018&nbsp;</span><span style="COLOR: #0000ff">finally</span><span style="COLOR: #000000">&nbsp;handler&nbsp;L_0018&nbsp;to&nbsp;L_0027<br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<p><br><br>从上面IL代码看出，处理流程跟以前处理str是一样的，只是因为引用类型特性的原因，返回的结果就跟值类型有所不同。<br><br>另外我们还看到IL处理try finally的时候，.NET1.1和.NET2.0生成的IL有少许不同。<a class=postTitle2 id=_b2a92868a5a_HomePageDays_DaysList_ctl00_DayItem_DayList_ctl02_TitleUrl href="http://www.cnitblog.com/seeyeah/archive/2008/06/13/45673.html"><u><font color=#800080>Quiz:who win in finally vs return? </font></u></a>中的是.NET1.1的版本。此为.NET2.0的版本。<br><br></p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/45746.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-06-14 11:36 <a href="http://www.cnitblog.com/seeyeah/archive/2008/06/14/45746.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>线程，同步与锁————Lock你到底锁住了谁 </title><link>http://www.cnitblog.com/seeyeah/archive/2008/06/13/45674.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Fri, 13 Jun 2008 14:56:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/06/13/45674.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/45674.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/06/13/45674.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/45674.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/45674.html</trackback:ping><description><![CDATA[引用：<a class=singleposttitle id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/city22/archive/2007/01/30/634948.html"><u><font color=#800080>线程，同步与锁————Lock你到底锁住了谁</font></u></a> <br>
<hr>
线程在多核时代的优势月来越明显，多线程编程的学习也提上议事日程。但越来越多的人陷入线程的泥潭，最后搞得自己面目全非。越来越多的死锁，越来越多的异常数据，在并发性测试中让一个个线程程序员焦头烂额。&#8220;自己在自己的编程环境下怎么都没事，单步调试也不会有任何错误，到了两个人，多个人测试的时候怎么就不行了呢？&#8221;线程，同步与锁的问题渐渐的凸现在了每个程序员的面前。<br>还是让我们一起来学习同步与锁吧。
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock是每个程序员都熟知的语句，但究竟它如何工作的呢?<br>我们先来看几个案例,看看lock是什么.<br></p>
<p>&nbsp;</p>
<span id=Codehighlighter1_32_478_Open_Text>
<p></span>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ThreadTest<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Test()<br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;t1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Thread(Thread1);<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;t2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Thread(Thread2);<br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1.Start();<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2.Start();<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Thread1()<br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.i);<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.Sleep(</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.i);<br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Thread2()<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.Sleep(</span><span style="COLOR: #000000">500</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Change&nbsp;the&nbsp;value&nbsp;in&nbsp;locking</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">26</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ThreadTest2<br></span><span style="COLOR: #008080">28</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">29</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">30</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Test()<br></span><span style="COLOR: #008080">31</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">32</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;t1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Thread(Thread1);<br></span><span style="COLOR: #008080">33</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;t2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Thread(Thread2);<br></span><span style="COLOR: #008080">34</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1.Start();<br></span><span style="COLOR: #008080">35</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2.Start();<br></span><span style="COLOR: #008080">36</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">37</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Thread1()<br></span><span style="COLOR: #008080">38</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">39</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">40</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">41</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.i);<br></span><span style="COLOR: #008080">42</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.Sleep(</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">43</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.i);<br></span><span style="COLOR: #008080">44</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">45</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">46</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Thread2()<br></span><span style="COLOR: #008080">47</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">48</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">lock</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">49</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="COLOR: #008080">50</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.Sleep(</span><span style="COLOR: #000000">500</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">51</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">52</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Can't&nbsp;change&nbsp;the&nbsp;value&nbsp;in&nbsp;locking</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">53</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">54</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="COLOR: #008080">55</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;两段程序有什么区别吗?看看吧,ThreadTest2.Thread2()中多了一个lock(this)却产生了不同的结果</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本想在案例一中lock住this对象,让其他的线程不能操作,可是事情不是像我们想象的那样lock(this)是lock this的意思.this中的属性依然能够被别的线程改变.那我们lock住的是什么?是代码段,是lock后面大括号中代码段,这段代码让多个人执行不不被允许的.那返回头来在看lock(this),this是什么意思呢?可以说this知识这段代码域的标志,看看案例二中Thread2.Thread2就明白了,Thread2中的lock需要等到Thread1种lock释放后才开始运行,释放之前一直处于等待状态,这就是标志的表现.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;好吧,让我们来了解一下,lock这段代码是怎么运行的.lock语句根本使用的就是Moniter.Enter和Moniter.Exit,也就是说lock(this)时执行Moniter.Enter(this),大括号结束时执行Monitor.Exit(this).他的意义在于什么呢,对于任何一个对象来说,他在内存中的第一部分放置的是所有方法的地址,第二部分放着一个索引,他指向CLR中的SyncBlock Cache区域中的一个SyncBlock.什么意思呢?就是说,当你执行Monitor.Enter（Object）时，如果object的索引值为负数，就从SyncBlock Cache中选区一个SyncBlock，将其地址放在object的索引中。这样就完成了以object为标志的锁定，其他的线程想再次进行Monitor.Enter(object)操作，将获得object为正数的索引，然后就等待。直到索引变为负数，即线程使用Monitor.Exit（object)将索引变为负数。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果明白了Monitor.Enter的原理,lock当然不再话下.当然lock后括号里面的值不是说把整个对象锁住,而是对他的一个值进行了修改,使别的lock不能锁住他,这才是lock(object)的真面目.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;但在实际使用中Monitor还是不推荐,还是lock好的,Monitor需要加上很多try catch才能保证安全性,但lock却帮我们做了,而且lock看起来更优雅.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在静态方法中如何使用lock呢,由于我们没有this可用,所以我们使用typeof(this)好了,Type也有相应的方法地址和索引,所以他也是可以来当作lock的标志的.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;但微软不提倡是用public的object或者typeof()或者字符串这样的标志就是因为,如果你的public object在其他的线程中被null并被垃圾收集了,将发生不可预期的错误.</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/45674.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-06-13 22:56 <a href="http://www.cnitblog.com/seeyeah/archive/2008/06/13/45674.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Quiz:who win in finally vs return? </title><link>http://www.cnitblog.com/seeyeah/archive/2008/06/13/45673.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Fri, 13 Jun 2008 14:52:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/06/13/45673.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/45673.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/06/13/45673.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/45673.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/45673.html</trackback:ping><description><![CDATA[引用：<a id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/gjcn/archive/2008/03/05/1091536.html"><u><font color=#800080>Quiz:who win in finally vs return? </font></u></a><br>
<hr>
<p>废话就不多讲了，直接看看下面的例子。<br>1）<font face=Verdana>static int Test()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int val = 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return val;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; finally<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; val = 2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>2）<span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> s_val;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> Test()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s_val = 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0000ff">try<br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> s_val;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: #0000ff">finally<br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s_val = 2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br>请问这两个例子最后的&nbsp;return value 是什么？<br>&nbsp;&nbsp;&nbsp;&nbsp; 我们仔细看看这两个了例子就知道2)与1）的不同在于前者使用静态变量代替局部变量。那么他们之间有什么不同么？<br>答案是他们的return value 是一样的，都是1。<br>便于讲解，我们拿出他们的IL代码看看：</p>
</font><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">.method&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;hidebysig&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;int32&nbsp;&nbsp;Test()&nbsp;cil&nbsp;managed<br>{<br>&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Code&nbsp;size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;16&nbsp;(0x10)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;.maxstack&nbsp;&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;.locals&nbsp;init&nbsp;([</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]&nbsp;int32&nbsp;val,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]&nbsp;int32&nbsp;CS$</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">$</span><span style="COLOR: #000000">0000</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;IL_0000:&nbsp;&nbsp;nop<br>&nbsp;&nbsp;IL_0001:&nbsp;&nbsp;ldc.i4.</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">int&nbsp;val=1</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;IL_0002:&nbsp;&nbsp;stloc.</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;.</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;IL_0003:&nbsp;&nbsp;nop<br>&nbsp;&nbsp;&nbsp;&nbsp;IL_0004:&nbsp;&nbsp;ldloc.</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">变量0（val）&nbsp;入栈</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;IL_0005:&nbsp;&nbsp;stloc.</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;这里建个中间隐藏变量1（$ret)放回栈顶的值（val）。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;IL_0006:&nbsp;&nbsp;leave.s&nbsp;&nbsp;&nbsp;&nbsp;IL_000d<br>&nbsp;&nbsp;}&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;end&nbsp;.try</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">finally</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;IL_0008:&nbsp;&nbsp;nop<br>&nbsp;&nbsp;&nbsp;&nbsp;IL_0009:&nbsp;&nbsp;ldc.i4.</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">int&nbsp;val=2&nbsp;并入栈</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;IL_000a:&nbsp;&nbsp;stloc.</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返回栈顶的值付给变量0（val）</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;IL_000b:&nbsp;&nbsp;nop<br>&nbsp;&nbsp;&nbsp;&nbsp;IL_000c:&nbsp;&nbsp;endfinally<br>&nbsp;&nbsp;}&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;end&nbsp;handler</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;IL_000d:&nbsp;&nbsp;nop<br>&nbsp;&nbsp;IL_000e:&nbsp;&nbsp;ldloc.</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">取出变量1（$ret）这就是放回值，但是这里我们可以看到val的值已经改变。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;IL_000f:&nbsp;&nbsp;ret<br>}&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;end&nbsp;of&nbsp;method&nbsp;Program::Test<br></span></div>
<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">.method&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;hidebysig&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;int32&nbsp;&nbsp;Test1()&nbsp;cil&nbsp;managed<br>{<br>&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Code&nbsp;size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;28&nbsp;(0x1c)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;.maxstack&nbsp;&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;.locals&nbsp;init&nbsp;([</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]&nbsp;int32&nbsp;CS$</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">$</span><span style="COLOR: #000000">0000</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;IL_0000:&nbsp;&nbsp;nop<br>&nbsp;&nbsp;IL_0001:&nbsp;&nbsp;ldc.i4.</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;值1入栈。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;IL_0002:&nbsp;&nbsp;stsfld&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int32&nbsp;ConsoleApp.Program::s_val&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">将栈顶值传给静态变量</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;.</span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;IL_0007:&nbsp;&nbsp;nop<br>&nbsp;&nbsp;&nbsp;&nbsp;IL_0008:&nbsp;&nbsp;ldsfld&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int32&nbsp;ConsoleApp.Program::s_val&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">取出静态变量</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;IL_000d:&nbsp;&nbsp;stloc.</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">从栈顶取出的值传给局部变量0的隐藏变量（这里静态变量不是局部变量0）</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;IL_000e:&nbsp;&nbsp;leave.s&nbsp;&nbsp;&nbsp;&nbsp;IL_0019<br>&nbsp;&nbsp;}&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;end&nbsp;.try</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">finally</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;IL_0010:&nbsp;&nbsp;nop<br>&nbsp;&nbsp;&nbsp;&nbsp;IL_0011:&nbsp;&nbsp;ldc.i4.</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">同上</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;IL_0012:&nbsp;&nbsp;stsfld&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int32&nbsp;ConsoleApp.Program::s_val&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">存储静态变量为2</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;IL_0017:&nbsp;&nbsp;nop<br>&nbsp;&nbsp;&nbsp;&nbsp;IL_0018:&nbsp;&nbsp;endfinally<br>&nbsp;&nbsp;}&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;end&nbsp;handler</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;IL_0019:&nbsp;&nbsp;nop<br>&nbsp;&nbsp;IL_001a:&nbsp;&nbsp;ldloc.</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">取出局部变量0的值作为返回值。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;IL_001b:&nbsp;&nbsp;ret<br>}&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;end&nbsp;of&nbsp;method&nbsp;Program::Test1<br></span></div>
<br><br>这里无论是那种方式，都是生成一个隐藏变量存储返回值的，并不是直接返回变量的地址的。<br>如果大家多CLR的工作原理有所了解的话，应该不是很难理解，CLR对一个线程堆栈分配的是方法的局部变量和方法返回值。一个方法在线程堆栈中由它的实参开始到返回值结束。因此放回值是有自己的存储地址的。这样就可以解释上面的问题，看起来很像 { return i++ ；}<br>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/45673.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-06-13 22:52 <a href="http://www.cnitblog.com/seeyeah/archive/2008/06/13/45673.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原]jQuery调用WebService</title><link>http://www.cnitblog.com/seeyeah/archive/2008/06/12/45471.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 11 Jun 2008 16:59:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/06/12/45471.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/45471.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/06/12/45471.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/45471.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/45471.html</trackback:ping><description><![CDATA[<hr>
<br>1、编写4种WebService方法<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;[WebService(Namespace&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://tempuri.org/</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)]<br>&nbsp;&nbsp;&nbsp;&nbsp;[WebServiceBinding(ConformsTo&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;WsiProfiles.BasicProfile1_1)]<br>&nbsp;&nbsp;&nbsp;&nbsp;[ScriptService]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">令WebService成功传入Json参数，并以Json形式返回结果</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;[GenerateScriptType(</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(Person))]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">不是必要，但推荐添加(如果Person里面再嵌套另一个复杂类型，则必要声明)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;[ToolboxItem(</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">)]<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;WebService1&nbsp;:&nbsp;System.Web.Services.WebService<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;summary&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;无任何参数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;/summary&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;returns&gt;&lt;/returns&gt;</span><span style="COLOR: #808080"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[WebMethod]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;HelloWorld()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello&nbsp;World</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;summary&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;传入参数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;/summary&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;param&nbsp;name="name"&gt;&lt;/param&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;returns&gt;&lt;/returns&gt;</span><span style="COLOR: #808080"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[WebMethod]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;Hello(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;name)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">.Format(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello&nbsp;{0}</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;summary&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;返回泛型列表<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;/summary&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;param&nbsp;name="i"&gt;&lt;/param&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;returns&gt;&lt;/returns&gt;</span><span style="COLOR: #808080"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[WebMethod]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;CreateArray(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;list&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(i&nbsp;</span><span style="COLOR: #000000">&gt;=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.Add(i</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;list;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;summary&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;返回复杂类型<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;/summary&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;param&nbsp;name="name"&gt;&lt;/param&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;param&nbsp;name="age"&gt;&lt;/param&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;returns&gt;&lt;/returns&gt;</span><span style="COLOR: #808080"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[WebMethod]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Person&nbsp;GetPerson(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;name,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;age)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Person()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;name,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Age&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;age<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;summary&gt;</span><span style="COLOR: #008000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;复杂类型<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;</span><span style="COLOR: #808080">&lt;/summary&gt;</span><span style="COLOR: #808080"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Person<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;Name&nbsp;{&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Age&nbsp;{&nbsp;</span><span style="COLOR: #0000ff">get</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #0000ff">set</span><span style="COLOR: #000000">;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br>2、编写js调用以上方法<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000; BACKGROUND-COLOR: #ffff00">&lt;%</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">@&nbsp;Page&nbsp;Language</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">C#</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;AutoEventWireup</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">true</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;CodeBehind</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">WebForm1.aspx.cs</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;Inherits</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">WebApplication1.WebForm1</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #ffff00">%&gt;</span><span style="COLOR: #000000"><br><br></span><span style="COLOR: #0000ff">&lt;!</span><span style="COLOR: #ff00ff">DOCTYPE&nbsp;html&nbsp;PUBLIC&nbsp;"-//W3C//DTD&nbsp;XHTML&nbsp;1.0&nbsp;Transitional//EN"&nbsp;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">html&nbsp;</span><span style="COLOR: #ff0000">xmlns</span><span style="COLOR: #0000ff">="http://www.w3.org/1999/xhtml"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">head&nbsp;</span><span style="COLOR: #ff0000">runat</span><span style="COLOR: #0000ff">="server"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">title</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">无标题页</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">title</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">style&nbsp;</span><span style="COLOR: #ff0000">type</span><span style="COLOR: #0000ff">="text/css"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #800000; BACKGROUND-COLOR: #f5f5f5"><br>&nbsp;&nbsp;&nbsp;&nbsp;input<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{</span><span style="COLOR: #ff0000; BACKGROUND-COLOR: #f5f5f5"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">:</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">200px</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">;</span><span style="COLOR: #ff0000; BACKGROUND-COLOR: #f5f5f5"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">}</span><span style="COLOR: #800000; BACKGROUND-COLOR: #f5f5f5"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">style</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">script&nbsp;</span><span style="COLOR: #ff0000">type</span><span style="COLOR: #0000ff">="text/javascript"</span><span style="COLOR: #ff0000">&nbsp;src</span><span style="COLOR: #0000ff">="jquery-1[1].2.6.min.js"</span><span style="COLOR: #0000ff">&gt;&lt;/</span><span style="COLOR: #800000">script</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">script&nbsp;</span><span style="COLOR: #ff0000">type</span><span style="COLOR: #0000ff">="text/javascript"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"><br>&nbsp;&nbsp;&nbsp;&nbsp;$(</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">(){&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">/*</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1、WebService请求类型都为Post，WebService的Url为&#8220;[WebServiceUrl]/[WebMethod]&#8221;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2、contentType声明为Json<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3、data要用Json的字符串格式传入<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4、设置了dataType为json后，result就直接为返回的Json对象。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">*/</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">调用无参数方法</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><br></span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">#btnHelloWorld</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">).click(</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$.ajax({<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type:&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">POST</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;contentType:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">application/json</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">WebService1.asmx/HelloWorld</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{}</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataType:'json',<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;success:</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">(result){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(result.d);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">传入1个参数</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><br></span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">#btnHello</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">).click(</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$.ajax({<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type:&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">POST</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;contentType:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">application/json</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">WebService1.asmx/Hello</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{name:'KiMoGiGi'}</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataType:'json',<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;success:</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">(result){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(result.d);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">返回泛型列表</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><br></span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">#btnArray</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">).click(</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$.ajax({<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type:&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">POST</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;contentType:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">application/json</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">WebService1.asmx/CreateArray</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{i:10}</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataType:'json',<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;success:</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">(result){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(result.d.join(</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;|&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">//</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5">返回复杂类型</span><span style="COLOR: #008000; BACKGROUND-COLOR: #f5f5f5"><br></span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">#btnPerson</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">).click(</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$.ajax({<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type:&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">POST</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;contentType:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">application/json</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">WebService1.asmx/GetPerson</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">{name:'KiMoGiGi',age:26}</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataType:'json',<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;success:</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">function</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">(result){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">var</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;person&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;result.d;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">var</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;showText&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">=</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;[];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">for</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">(</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">var</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;p&nbsp;</span><span style="COLOR: #0000ff; BACKGROUND-COLOR: #f5f5f5">in</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;person){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;showText.push(p&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">+</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">:</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">+</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">&nbsp;person[p]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(showText.join(</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">\r\n</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">"</span><span style="COLOR: #000000; BACKGROUND-COLOR: #f5f5f5">));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;});<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">script</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">head</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">body</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">form&nbsp;</span><span style="COLOR: #ff0000">id</span><span style="COLOR: #0000ff">="form1"</span><span style="COLOR: #ff0000">&nbsp;runat</span><span style="COLOR: #0000ff">="server"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">p</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">input&nbsp;</span><span style="COLOR: #ff0000">type</span><span style="COLOR: #0000ff">="button"</span><span style="COLOR: #ff0000">&nbsp;id</span><span style="COLOR: #0000ff">="btnHelloWorld"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="HelloWorld"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">p</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">p</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">input&nbsp;</span><span style="COLOR: #ff0000">type</span><span style="COLOR: #0000ff">="button"</span><span style="COLOR: #ff0000">&nbsp;id</span><span style="COLOR: #0000ff">="btnHello"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="Hello"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">p</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">p</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">input&nbsp;</span><span style="COLOR: #ff0000">type</span><span style="COLOR: #0000ff">="button"</span><span style="COLOR: #ff0000">&nbsp;id</span><span style="COLOR: #0000ff">="btnArray"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="CreateArray"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">p</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">p</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">input&nbsp;</span><span style="COLOR: #ff0000">type</span><span style="COLOR: #0000ff">="button"</span><span style="COLOR: #ff0000">&nbsp;id</span><span style="COLOR: #0000ff">="btnPerson"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="GetPerson"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">p</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">form</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">body</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">html</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span></div>
<br><br>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/45471.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-06-12 00:59 <a href="http://www.cnitblog.com/seeyeah/archive/2008/06/12/45471.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Solving the Problem with Events: Weak Event Handlers</title><link>http://www.cnitblog.com/seeyeah/archive/2008/05/19/43909.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Mon, 19 May 2008 14:32:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/05/19/43909.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/43909.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/05/19/43909.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/43909.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/43909.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 摘至：Solving the Problem with Events: Weak Event HandlersThe Problem (A Recap)As discussed last time, delegates can produce memory leaks in our applications if not used carefully. Most often, th...&nbsp;&nbsp;<a href='http://www.cnitblog.com/seeyeah/archive/2008/05/19/43909.html'>阅读全文</a><img src ="http://www.cnitblog.com/seeyeah/aggbug/43909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-05-19 22:32 <a href="http://www.cnitblog.com/seeyeah/archive/2008/05/19/43909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>你真的了解Ioc与AOP吗？</title><link>http://www.cnitblog.com/seeyeah/archive/2008/05/14/43719.html</link><dc:creator>KiMoGiGi</dc:creator><author>KiMoGiGi</author><pubDate>Wed, 14 May 2008 13:29:00 GMT</pubDate><guid>http://www.cnitblog.com/seeyeah/archive/2008/05/14/43719.html</guid><wfw:comment>http://www.cnitblog.com/seeyeah/comments/43719.html</wfw:comment><comments>http://www.cnitblog.com/seeyeah/archive/2008/05/14/43719.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/seeyeah/comments/commentRss/43719.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/seeyeah/services/trackbacks/43719.html</trackback:ping><description><![CDATA[摘至：<a href="http://www.cnblogs.com/zhenyulu/articles/233966.html">http://www.cnblogs.com/zhenyulu/articles/233966.html</a><br>
<hr>
<p>本系列的全部源代码及二进制文件可以从这里下载：<a href="http://www.cnblogs.com/Files/zhenyulu/IocInCSharp.rar"><u><font color=#0000ff>IocInCSharp.rar</font></u></a> </p>
<p><a href="http://www.cnblogs.com/zhenyulu/articles/233966.html"><u><font color=#800080>你真的了解Ioc与AOP吗？（1）</font></u></a> </p>
<p><a href="http://www.cnblogs.com/zhenyulu/articles/233968.html"><u><font color=#0000ff>你真的了解Ioc与AOP吗？（2）</font></u></a> </p>
<p><a href="http://www.cnblogs.com/zhenyulu/articles/234069.html"><u><font color=#0000ff>你真的了解Ioc与AOP吗？（3）</font></u></a> </p>
<p><a href="http://www.cnblogs.com/zhenyulu/articles/234075.html"><u><font color=#0000ff>你真的了解Ioc与AOP吗？（4）</font></u></a> </p>
<p><a href="http://www.cnblogs.com/zhenyulu/articles/234074.html"><u><font color=#0000ff>你真的了解Ioc与AOP吗？（5）</font></u></a> </p>
<hr width="95%">
<p>本部分示例代码请参考"src\Step1"、"src\Step2"目录</p>
<p>你真的了解Ioc与AOP吗？我现在还不是很了解，而且越学习越发现自己了解的很少，Ioc与AOP中蕴涵了大量的能量等待我们去开发。在这个系列中，我仅仅利用Sping.net这个框架向大家展示一下Ioc与AOP的强大功能（呵呵，其实写这段话的目的是因为&#8220;文章题目&#8221;牛皮吹得有点大了，给自己个台阶下罢了）。</p>
<p>在这个系列中一共包含6个案例，从简单到复杂，也是对问题分解、思考和解决的一个过程，它们分别是：（1）类之间的依赖；（2）接口依赖；（3）基于配置文件和Reflection的工厂模式；（4）使用Spring.net实现Ioc；（5）Romoting；（6）利用Ioc在不动一行代码的情况下实现Remoting。为了更好的理解文中的内容，最好顺序阅读。</p>
<p>作为一个应用系统，代码复用至关重要。如果在你的设计中，类与类存在很强的相互关联，那么你会发现在重用这些组件时就存在很严重的问题。在Step1到Step3-Reflection的例子中，我们试图 利用&#8220;针对接口编程&#8221;以及自己设计的Ioc对系统进行解耦。在Step3到Step5的例子中，我们将利用Spring.net提供的Ioc框架，轻松完成解耦以及系统改造等工作。</p>
<img src ="http://www.cnitblog.com/seeyeah/aggbug/43719.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/seeyeah/" target="_blank">KiMoGiGi</a> 2008-05-14 21:29 <a href="http://www.cnitblog.com/seeyeah/archive/2008/05/14/43719.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>