<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_happyhippy</title><subtitle type="text">这个世界的问题在于聪明人充满疑惑，而傻子们坚信不疑。--罗素</subtitle><id>http://feed.cnblogs.com/blog/u/23645/rss</id><updated>2011-10-16T01:39:48Z</updated><author><name>Silent Void</name><uri>http://www.cnblogs.com/happyhippy/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/happyhippy/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/23645/rss"/><entry><id>http://www.cnblogs.com/happyhippy/archive/2011/07/17/2108976.html</id><title type="text">C#使用TCP/IP与ModBus进行通讯</title><summary type="text">1. ModBus的 Client/Server模型2. 数据包格式及MBAP header (MODBUS Application Protocol header)3. 大小端转换4. 事务标识和缓...</summary><published>2011-07-17T15:28:00Z</published><updated>2011-07-17T15:28:00Z</updated><author><name>Silent Void</name><uri>http://www.cnblogs.com/happyhippy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/happyhippy/archive/2011/07/17/2108976.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/happyhippy/archive/2011/07/17/2108976.html"/><content type="html">&lt;p&gt;1. ModBus的 Client/Server模型&lt;br&gt;2. 数据包格式及MBAP header (MODBUS Application Protocol header)&lt;br&gt;3. 大小端转换&lt;br&gt;4. 事务标识和缓冲清理&lt;br&gt;5. 示例代码&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;0. MODBUS MESSAGING ON TCP/IP IMPLEMENTATION GUIDE&lt;/p&gt; &lt;p&gt;下载地址：&lt;a href="http://www.modbus.org/docs/Modbus_Messaging_Implementation_Guide_V1_0b.pdf"&gt;http://www.modbus.org/docs/Modbus_Messaging_Implementation_Guide_V1_0b.pdf&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;1. ModBus的 Client/Server模型&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/201107172327421591.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/201107172327428145.png" width="703" height="186"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Client与Server之间有两种通讯方式：一种是TCP/IP，另一种是通过串口(Serial Port)，本文重点介绍第一种通讯方式。第二种方式留了接口，暂时还没有实现。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;2. 数据包格式及MBAP header (MODBUS Application Protocol header) &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2.1 数据包格式&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/201107172327432539.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/20110717232744521.png" width="573" height="169"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;数据交换过程中，数据包的格式由三部分组成：协议头 + 功能码 + 数据(请求或接受的数据)。&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里主要用到下列两个功能码（十进制）：&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3: 读取寄存器中的值（Read Multiple Register）&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 16: 往寄存器中写值（Write Multiple Register）&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp; 2.2 MBAP header&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/20110717232746290.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/201107172327483995.png" width="660" height="358"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;协议头具体包括下列4个字段：&lt;br&gt;(1) Transaction Identifier：事务ID标识，Client每发送一个Request数据包的时候，需要带上该标识；当Server响应该请求的时候，会把该标识复制到Response中；这样客户端就可以进行容错判断，防止数据包发串了。&lt;br&gt;(2) Protocal Identifier：协议标识，ModBus协议中，该值为0；&lt;br&gt;(3) Length：整个数据包中，从当个前这个字节之后开始计算，后续数据量的大小(按byte计算)。&lt;br&gt;(4) Unit Identifier：-_-&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;3. 大小端转换&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;ModBus使用Big-Endian表示地址和数据项。因此在发送或者接受数据的过程中，需要对数据进行转换。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;3.1 判断大小端&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/201107172327493307.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Endian" border="0" alt="Endian" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/201107172327514778.jpg" width="667" height="312"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;对于整数1，在两种机器上有两种不同的标示方式，如上图所示；因此，我们可以用&amp;amp;操作符来取其地址，再转换成指向byte的指针(byte*)，最后再取该指针的值；若得到的byte值为1，则为Little-Endian，否则为Big-Endian。&lt;/p&gt; &lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt; &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;unsafe&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; tester = 1;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; littleEndian = (*(&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;*)(&amp;amp;tester)) == (&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;)1;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3.2 整数/浮点数转换成Byte数组&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;.Net提供了现成的API，可以BitConverter.GetBytes(value)和BitConverter.ToXXOO(Byte[] data)来进行转换。下面的代码对该转换进行了封装，加入了Little-Endian转Big-Endian的处理（以int为例）：&lt;/p&gt;&#xD;
&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;&#xD;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ValueHelper &lt;font color="#ff0000"&gt;//Big-Endian可以直接转换&lt;/font&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; Byte[] GetBytes(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; BitConverter.GetBytes(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; GetInt(&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] data)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; BitConverter.ToInt32(data, 0);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; LittleEndianValueHelper : ValueHelper &lt;font color="#ff0000"&gt;//Little-Endian，转换时需要做翻转处理。&lt;/font&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; Byte[] GetBytes(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Reverse(BitConverter.GetBytes(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;));&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; GetInt(&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] data)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; BitConverter.ToInt32(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Reverse(data), 0);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; Byte[] Reverse(Byte[] data)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;             Array.Reverse(data);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; data;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4. 事务标识和缓冲处理&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.1 Transaction Identifier&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;上面2.2节中提到，Client每发送一个Request数据包的时候，需要带上一个标识；当Server响应该请求的时候，会把该标识复制到Response中，返回给Client。这样Client就可以用来判断数据包有没有发串。在程序中，可以可以用一个变量及记录该标识：&lt;/p&gt;&#xD;
&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;&#xD;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt; dataIndex = 0;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt; CurrentDataIndex&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;        get { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.dataIndex; }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt; NextDataIndex()&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; ++&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.dataIndex;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;每次Client发送数据的时候，调用NextDataIndex()来取得事务标识；接着当Client读取Server的返回值的时候，需要判断数据包中的数据标识是否与发送时的标志一致；如果一致，则认为数据包有效；否则丢掉无效的数据包。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.2 缓冲处理&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;上节中提到，如果Client接收到的响应数据包中的标识，与发送给Server的数据标识不一致，则认为Server返回的数据包无效，并丢弃该数据包。&lt;/p&gt;&#xD;
&lt;p&gt;如果只考虑正常情况，即数据木有差错，Client每次发送请求后，其请求包里面包含需要读取的寄存器数量，能算出从Server返回的数据两大小，这样就能确定读完Server返回的所有缓冲区中的数据；每次交互后，Socket缓冲区中都为空，则整个过程没有问题。但是问题是：如果Server端出错，或者数据串包等异常情况下，Client不能确定Server返回的数据包(占用的缓冲区)有多大；如果缓冲区中的数据没有读完，下次再从缓冲区中接着读的时候，数据包必然是不正确的，而且会错误会一直延续到后续的读取操作中。&lt;/p&gt;&#xD;
&lt;p&gt;因此，每次读取数据时，要么全部读完缓冲区中的数据，要么读到错误的时候，就必须清楚缓冲区中剩余的数据。网上搜了半天，木有找到Windows下如何清理Socket缓冲区的。有篇文章倒是提到一个狠招，每次读完数据后，直接把Socket给咔嚓掉；然后下次需要读取或发送数据的时候，再重新建立Socket连接。&lt;/p&gt;&#xD;
&lt;p&gt;回过头再来看，其实，在Client与Server进行交互的过程中，Server每次返回的数据量都不大，也就一个MBAP Header + 几十个寄存器的值。因此，另一个处理方式，就是每次读取尽可能多的数据(多过缓冲区中的数据量)，多读的内容，再忽略掉。暂时这么处理，期待有更好的解决方法。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;5. 源代码&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;5.1 类图结构：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/201107172327539497.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="ClassDiagram1" border="0" alt="ClassDiagram1" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/201107172327575546.jpg" width="855" height="679"&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;5.2 使用示例&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;(1) 写入数据：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;&#xD;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Wrapper.Send(Encoding.ASCII.GetBytes(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.tbxSendText.Text.Trim()));&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Send(&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] data)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//[0]:填充0，清掉剩余的寄存器&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (data.Length &amp;lt; 60)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         var input = data;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         data = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Byte[60];&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         Array.Copy(input, data, input.Length);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Connect();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     List&amp;lt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&amp;gt; values = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; List&amp;lt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&amp;gt;(255);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//[1].Write Header：MODBUS Application Protocol header&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     values.AddRange(ValueHelper.Instance.GetBytes(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.NextDataIndex()));&lt;span style="color: #008000"&gt;//1~2.(Transaction Identifier)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;     values.AddRange(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Byte[] { 0, 0 });&lt;span style="color: #008000"&gt;//3~4:Protocol Identifier,0 = MODBUS protocol&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;     values.AddRange(ValueHelper.Instance.GetBytes((&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;)(data.Length + 7)));&lt;span style="color: #008000"&gt;//5~6:后续的Byte数量&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;     values.Add(0);&lt;span style="color: #008000"&gt;//7:Unit Identifier:This field is used for intra-system routing purpose.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;     values.Add((&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;)FunctionCode.Write);&lt;span style="color: #008000"&gt;//8.Function Code : 16 (Write Multiple Register)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;     values.AddRange(ValueHelper.Instance.GetBytes(StartingAddress));&lt;span style="color: #008000"&gt;//9~10.起始地址&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;     values.AddRange(ValueHelper.Instance.GetBytes((&lt;span style="color: #0000ff"&gt;short&lt;/span&gt;)(data.Length / 2)));&lt;span style="color: #008000"&gt;//11~12.寄存器数量&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;     values.Add((&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;)data.Length);&lt;span style="color: #008000"&gt;//13.数据的Byte数量&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//[2].增加数据&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     values.AddRange(data);&lt;span style="color: #008000"&gt;//14~End:需要发送的数据&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//[3].写数据&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.socketWrapper.Write(values.ToArray());&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//[4].防止连续读写引起前台UI线程阻塞&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;     Application.DoEvents();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//[5].读取Response: 写完后会返回12个byte的结果&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] responseHeader = &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.socketWrapper.Read(12);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  36:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;strong&gt;(2) 读取数据：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;&#xD;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.tbxReceiveText.Text = Encoding.ASCII.GetString(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Wrapper.Receive());&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] Receive()&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Connect();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;             List&amp;lt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&amp;gt; sendData = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; List&amp;lt;&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;&amp;gt;(255);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;             &lt;span style="color: #008000"&gt;//[1].Send&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;             sendData.AddRange(ValueHelper.Instance.GetBytes(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.NextDataIndex()));&lt;span style="color: #008000"&gt;//1~2.(Transaction Identifier)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;             sendData.AddRange(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Byte[] { 0, 0 });&lt;span style="color: #008000"&gt;//3~4:Protocol Identifier,0 = MODBUS protocol&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;             sendData.AddRange(ValueHelper.Instance.GetBytes((&lt;span style="color: #0000ff"&gt;short&lt;/span&gt;)6));&lt;span style="color: #008000"&gt;//5~6:后续的Byte数量（针对读请求，后续为6个byte）&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;             sendData.Add(0);&lt;span style="color: #008000"&gt;//7:Unit Identifier:This field is used for intra-system routing purpose.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;             sendData.Add((&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;)FunctionCode.Read);&lt;span style="color: #008000"&gt;//8.Function Code : 3 (Read Multiple Register)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;             sendData.AddRange(ValueHelper.Instance.GetBytes(StartingAddress));&lt;span style="color: #008000"&gt;//9~10.起始地址&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;             sendData.AddRange(ValueHelper.Instance.GetBytes((&lt;span style="color: #0000ff"&gt;short&lt;/span&gt;)30));&lt;span style="color: #008000"&gt;//11~12.需要读取的寄存器数量&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.socketWrapper.Write(sendData.ToArray()); &lt;span style="color: #008000"&gt;//发送读请求&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;             &lt;span style="color: #008000"&gt;//[2].防止连续读写引起前台UI线程阻塞&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;             Application.DoEvents();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;             &lt;span style="color: #008000"&gt;//[3].读取Response Header : 完后会返回8个byte的Response Header&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] receiveData = &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.socketWrapper.Read(256);&lt;span style="color: #008000"&gt;//缓冲区中的数据总量不超过256byte，一次读256byte，防止残余数据影响下次读取&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;short&lt;/span&gt; identifier = (&lt;span style="color: #0000ff"&gt;short&lt;/span&gt;)((((&lt;span style="color: #0000ff"&gt;short&lt;/span&gt;)receiveData[0]) &amp;lt;&amp;lt; 8) + receiveData[1]);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;             &lt;span style="color: #008000"&gt;//[4].读取返回数据：根据ResponseHeader，读取后续的数据&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (identifier != &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.CurrentDataIndex) &lt;span style="color: #008000"&gt;//请求的数据标识与返回的标识不一致，则丢掉数据包&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Byte[0];&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt; length = receiveData[8];&lt;span style="color: #008000"&gt;//最后一个字节，记录寄存器中数据的Byte数&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] result = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[length];&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;             Array.Copy(receiveData, 9, result, 0, length);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; result;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;         }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;strong&gt;(3) 测试发送和读取：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/201107172328003787.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="DataPackage" border="0" alt="DataPackage" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201107/201107172328067587.jpg" width="1034" height="699"&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;ModBus-TCP Client Tool（可以从网上下载，用来测试）中，可以点击“Edit Values”，修改寄存器中的值；然后再在测试程序中，点击“接收”，可以解析到修改后的值。这里只是测试发送和接收字符串，如果需要处理复杂的数字/字符串组合啥的，就需要自己定义数据格式和解析方式了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;5.3 代码下载&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://files.cnblogs.com/happyhippy/CSharpModBusExample.rar" target="_blank"&gt;CSharpModBusExample&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:03ba1a78-a866-44bc-a0ec-3b48572c3d55" &gt;标签: &lt;a href="http://technorati.com/tags/ModBus" rel="tag"&gt;ModBus&lt;/a&gt;,&lt;a href="http://technorati.com/tags/%e5%a4%a7%e5%b0%8f%e7%ab%af" rel="tag"&gt;大小端&lt;/a&gt;,&lt;a href="http://technorati.com/tags/TCP%2fIP" rel="tag"&gt;TCP/IP&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Socket%e7%bc%93%e5%86%b2%e5%8c%ba" rel="tag"&gt;Socket缓冲区&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/happyhippy/aggbug/2108976.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/happyhippy/archive/2011/07/17/2108976.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/happyhippy/archive/2011/07/02/2096482.html</id><title type="text">ProtocolException : 已超过传入消息(65536)的最大消息大小配额。</title><summary type="text">SilverLight调用WCF，提交的是一个List&amp;lt;Linq2SqlEntity&amp;gt;；当List中数据量不大的时候，不会报错；当数据量稍微大一点儿，就会出现这个错误。发生了 System.ServiceModel.ProtocolException Message=已超过传入消息(65536)的最大消息大小配额。若要增加配额，请使用相应绑定元素上的 MaxReceivedMessageSize ...</summary><published>2011-07-02T13:40:00Z</published><updated>2011-07-02T13:40:00Z</updated><author><name>Silent Void</name><uri>http://www.cnblogs.com/happyhippy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/happyhippy/archive/2011/07/02/2096482.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/happyhippy/archive/2011/07/02/2096482.html"/><content type="html">&lt;p&gt;SilverLight调用WCF，提交的是一个List&amp;lt;Linq2SqlEntity&amp;gt;；当List中数据量不大的时候，不会报错；当数据量稍微大一点儿，就会出现这个错误。发生了 System.ServiceModel.&lt;strong&gt;ProtocolException&lt;/strong&gt;&lt;br&gt;&amp;nbsp; Message=已超过传入消息(65536)的最大消息大小配额。若要增加配额，请使用相应绑定元素上的 MaxReceivedMessageSize 属性。&lt;br&gt;&amp;nbsp; Source=System.ServiceModel&lt;br&gt;&amp;nbsp; StackTrace:&lt;br&gt;&amp;nbsp; 在 System.ServiceModel.Channels.HttpInput.ThrowHttpProtocolException(String message, HttpStatusCode statusCode, String statusDescription) &lt;p&gt;&lt;p&gt;费了牛劲在网上搜了一通，有的说是要修改behavior的maxItemsInObjectGraph，有的说要修改binding的maxBufferSize/maxReceivedMessageSize，有的说要增加readerQuotas，有的是endpoint没有与自定义binding配置节关联起来，有的说要客户端和服务器端都要改(我的应用中，接受数据的是服务器端，客户端负责提交，所以应该不关客户端的事儿)。。。然后把server端的配置文件调整成下面这样：&lt;/p&gt; &lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt; &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &amp;lt;system.serviceModel&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;   &amp;lt;behaviors&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &amp;lt;serviceBehaviors&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;       &amp;lt;behavior name=&lt;span style="color: #006080"&gt;"MessageHeaderOperationBehaviourAuthenticationBehavior"&lt;/span&gt;&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         &amp;lt;dataContractSerializer &lt;font color="#ff0000"&gt;maxItemsInObjectGraph=&lt;span style="color: #006080"&gt;"&lt;strong&gt;2147483647&lt;/strong&gt;"&lt;/span&gt;&lt;/font&gt;/&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         &amp;lt;serviceMetadata httpGetEnabled=&lt;span style="color: #006080"&gt;"true"&lt;/span&gt;/&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         &amp;lt;serviceDebug includeExceptionDetailInFaults=&lt;span style="color: #006080"&gt;"true"&lt;/span&gt;/&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;       &amp;lt;/behavior&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &amp;lt;/serviceBehaviors&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;   &amp;lt;/behaviors&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;   &amp;lt;serviceHostingEnvironment aspNetCompatibilityEnabled=&lt;span style="color: #006080"&gt;"true"&lt;/span&gt; multipleSiteBindingsEnabled=&lt;span style="color: #006080"&gt;"true"&lt;/span&gt;/&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;   &amp;lt;services&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     &amp;lt;service behaviorConfiguration=&lt;span style="color: #006080"&gt;"MessageHeaderOperationBehaviourAuthenticationBehavior"&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;              name=&lt;span style="color: #006080"&gt;"MessageHeaderOperationBehaviourAuthentication"&lt;/span&gt;&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;       &amp;lt;endpoint address=&lt;span style="color: #006080"&gt;""&lt;/span&gt; binding=&lt;span style="color: #006080"&gt;"basicHttpBinding"&lt;/span&gt; &lt;font color="#ff0000"&gt;bindingConfiguration&lt;/font&gt;=&lt;span style="color: #006080"&gt;"&lt;strong&gt;&lt;font color="#ff0000"&gt;LargeSize&lt;/font&gt;&lt;/strong&gt;"&lt;/span&gt; contract=&lt;span style="color: #006080"&gt;"DyeService"&lt;/span&gt;&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;       &amp;lt;/endpoint&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;     &amp;lt;/service&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;   &amp;lt;/services&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;   &amp;lt;bindings&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;     &amp;lt;basicHttpBinding&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;       &amp;lt;binding name=&lt;span style="color: #006080"&gt;"&lt;font color="#ff0000"&gt;&lt;strong&gt;LargeSize&lt;/strong&gt;&lt;/font&gt;"&lt;/span&gt;  maxBufferSize=&lt;span style="color: #006080"&gt;"2147483647"&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;                maxBufferPoolSize=&lt;span style="color: #006080"&gt;"21474836471"&lt;/span&gt; &lt;font color="#ff0000"&gt;maxReceivedMessageSize=&lt;span style="color: #006080"&gt;"2147483647"&lt;/span&gt;&amp;gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         &amp;lt;&lt;font color="#ff0000"&gt;readerQuotas&lt;/font&gt; maxDepth=&lt;span style="color: #006080"&gt;"2147483647"&lt;/span&gt; maxStringContentLength=&lt;span style="color: #006080"&gt;"2147483647"&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;                       maxArrayLength=&lt;span style="color: #006080"&gt;"2147483647"&lt;/span&gt; maxBytesPerRead=&lt;span style="color: #006080"&gt;"2147483647"&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;                       maxNameTableCharCount=&lt;span style="color: #006080"&gt;"2147483647"&lt;/span&gt; /&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;         &amp;lt;security mode=&lt;span style="color: #006080"&gt;"None"&lt;/span&gt; /&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;       &amp;lt;/binding&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;     &amp;lt;/basicHttpBinding&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;   &amp;lt;/bindings&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt; &amp;lt;/system.serviceModel&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;但是问题依旧。最后在stackoverflow找到了正解：&lt;a href="http://stackoverflow.com/questions/4186938/wcf-error-unexpected-response-400-bad-request"&gt;WCF Error - unexpected response: (400) Bad Request.&lt;/a&gt;，里面链接到了另一篇帖子：&lt;a href="http://forums.silverlight.net/forums/p/191589/442381.aspx" target="_blank"&gt;Cannot get the MaxReceivedMessageSize higher than (65536)&lt;/a&gt;&#xD;
&lt;p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000" size="2"&gt;解决办法就是：配置文件中，service 的name属性必须与服务的类型全名称保持一致，才能应用上自定义的配置节。&lt;/font&gt;&lt;/strong&gt;&#xD;
&lt;p&gt;按着这个方法，调整之后的配置文件如下所示（删掉了其他无关的maxItemsInObjectGraph、readerQuotas等）：&lt;/p&gt;&#xD;
&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;&#xD;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;   &amp;lt;system.serviceModel&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &amp;lt;behaviors&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;       &amp;lt;serviceBehaviors&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         &amp;lt;behavior name=&lt;span style="color: #006080"&gt;"MessageHeaderOperationBehaviourAuthenticationBehavior"&lt;/span&gt;&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;           &amp;lt;serviceMetadata httpGetEnabled=&lt;span style="color: #006080"&gt;"true"&lt;/span&gt;/&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;           &amp;lt;serviceDebug includeExceptionDetailInFaults=&lt;span style="color: #006080"&gt;"true"&lt;/span&gt;/&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &amp;lt;/behavior&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;       &amp;lt;/serviceBehaviors&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &amp;lt;/behaviors&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &amp;lt;serviceHostingEnvironment aspNetCompatibilityEnabled=&lt;span style="color: #006080"&gt;"true"&lt;/span&gt; multipleSiteBindingsEnabled=&lt;span style="color: #006080"&gt;"true"&lt;/span&gt;/&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &amp;lt;services&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;       &amp;lt;service behaviorConfiguration=&lt;span style="color: #006080"&gt;"MessageHeaderOperationBehaviourAuthenticationBehavior"&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;                &lt;font color="#ff0000" size="4"&gt;name=&lt;span style="color: #006080"&gt;"NameSpace.DyeService"&lt;/span&gt;&amp;gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;         &amp;lt;endpoint address=&lt;span style="color: #006080"&gt;""&lt;/span&gt; binding=&lt;span style="color: #006080"&gt;"basicHttpBinding"&lt;/span&gt; &lt;font color="#ff0000"&gt;&lt;font size="4"&gt;bindingConfiguration=&lt;span style="color: #006080"&gt;"LargeSize"&lt;/span&gt;&lt;/font&gt;&lt;/font&gt; &lt;font size="4"&gt;&lt;font color="#ff0000"&gt;contract=&lt;span style="color: #006080"&gt;"NameSpace.DyeService"&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;         &amp;lt;/endpoint&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;       &amp;lt;/service&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;     &amp;lt;/services&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;     &amp;lt;bindings&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;       &amp;lt;basicHttpBinding&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;         &amp;lt;binding &lt;font size="4"&gt;&lt;font color="#ff0000"&gt;name=&lt;span style="color: #006080"&gt;"LargeSize"&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;  maxBufferSize=&lt;span style="color: #006080"&gt;"2147483647"&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;                  maxBufferPoolSize=&lt;span style="color: #006080"&gt;"21474836471"&lt;/span&gt; maxReceivedMessageSize=&lt;span style="color: #006080"&gt;"2147483647"&lt;/span&gt;&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;         &amp;lt;/binding&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;       &amp;lt;/basicHttpBinding&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     &amp;lt;/bindings&amp;gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;   &amp;lt;/system.serviceModel&amp;gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:0cc19e9f-9a55-48c0-ab7c-0d0cd8211ae8" &gt;标签: &lt;a href="http://technorati.com/tags/WCF" rel="tag"&gt;WCF&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ProtocalException" rel="tag"&gt;ProtocalException&lt;/a&gt;,&lt;a href="http://technorati.com/tags/65535" rel="tag"&gt;65535&lt;/a&gt;,&lt;a href="http://technorati.com/tags/SilverLight" rel="tag"&gt;SilverLight&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/happyhippy/aggbug/2096482.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/happyhippy/archive/2011/07/02/2096482.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/happyhippy/archive/2011/06/26/2090468.html</id><title type="text">ESC/P打印：程序控制打印机自动进退纸</title><summary type="text">打印连续纸张的时候，经常会遇到需要自动进退纸的功能，譬如下列场景：1. 打印完一个小标；(自动进纸)2. 用户撕断打印出来的小标；3. (自动退纸，纸张归位) 接着打印下一个小标； 下列代码在爱普生LQ 730k打印机上测试通过： 1: //使用示例 2: new PrintDirect(&amp;quot;PrinterName&amp;quot;).PrintESC(1);//打印后进纸 3: new PrintDirect(&amp;quot;...</summary><published>2011-06-25T16:00:00Z</published><updated>2011-06-25T16:00:00Z</updated><author><name>Silent Void</name><uri>http://www.cnblogs.com/happyhippy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/happyhippy/archive/2011/06/26/2090468.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/happyhippy/archive/2011/06/26/2090468.html"/><content type="html">&lt;p&gt;打印连续纸张的时候，经常会遇到需要自动进退纸的功能，譬如下列场景：&lt;br&gt;1. 打印完一个小标；(自动进纸)&lt;br&gt;2. 用户撕断打印出来的小标；&lt;br&gt;3. (自动退纸，纸张归位) 接着打印下一个小标；&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;下列代码在爱普生LQ 730k打印机上测试通过：&lt;/p&gt; &lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt; &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;//使用示例&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; PrintDirect(&lt;span style="color: #006080"&gt;"PrinterName"&lt;/span&gt;).PrintESC(1);&lt;span style="color: #008000"&gt;//打印后进纸&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; PrintDirect(&lt;span style="color: #006080"&gt;"PrinterName"&lt;/span&gt;).PrintESC(0);//打印前退纸&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;源代码：&lt;/p&gt;&#xD;
&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;&#xD;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;     [StructLayout(LayoutKind.Sequential)]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;struct&lt;/span&gt; DOCINFO&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         [MarshalAs(UnmanagedType.LPWStr)]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; pDocName;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         [MarshalAs(UnmanagedType.LPWStr)]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; pOutputFile;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         [MarshalAs(UnmanagedType.LPWStr)]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; pDataType;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; PrintDirect&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; PrintPort { get; set; }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; PrintDirect(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; port)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.PrintPort = port;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;         [DllImport(&lt;span style="color: #006080"&gt;"winspool.drv"&lt;/span&gt;, CharSet = CharSet.Unicode, ExactSpelling = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;, CallingConvention = CallingConvention.StdCall)]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;extern&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; OpenPrinter(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; pPrinterName, &lt;span style="color: #0000ff"&gt;ref&lt;/span&gt; IntPtr phPrinter, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; pDefault);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;         [DllImport(&lt;span style="color: #006080"&gt;"winspool.drv"&lt;/span&gt;, CharSet = CharSet.Unicode, ExactSpelling = &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;, CallingConvention = CallingConvention.StdCall)]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;extern&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; StartDocPrinter(IntPtr hPrinter, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Level, &lt;span style="color: #0000ff"&gt;ref&lt;/span&gt; DOCINFO pDocInfo);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;         [DllImport(&lt;span style="color: #006080"&gt;"winspool.drv"&lt;/span&gt;, CharSet = CharSet.Unicode, ExactSpelling = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;, CallingConvention = CallingConvention.StdCall)]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;extern&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; StartPagePrinter(IntPtr hPrinter);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;         [DllImport(&lt;span style="color: #006080"&gt;"winspool.drv"&lt;/span&gt;, CharSet = CharSet.Ansi, ExactSpelling = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;, CallingConvention = CallingConvention.StdCall)]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;extern&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; WritePrinter(IntPtr hPrinter, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; data, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; buf, &lt;span style="color: #0000ff"&gt;ref&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; pcWritten);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;         [DllImport(&lt;span style="color: #006080"&gt;"winspool.drv"&lt;/span&gt;, CharSet = CharSet.Unicode, ExactSpelling = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;, CallingConvention = CallingConvention.StdCall)]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;extern&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; EndPagePrinter(IntPtr hPrinter);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;         [DllImport(&lt;span style="color: #006080"&gt;"winspool.drv"&lt;/span&gt;, CharSet = CharSet.Unicode, ExactSpelling = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;, CallingConvention = CallingConvention.StdCall)]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;extern&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; EndDocPrinter(IntPtr hPrinter);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  39:&lt;/span&gt;         [DllImport(&lt;span style="color: #006080"&gt;"winspool.drv"&lt;/span&gt;, CharSet = CharSet.Unicode, ExactSpelling = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;, CallingConvention = CallingConvention.StdCall)]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  40:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;extern&lt;/span&gt; &lt;span style="color: #0000ff"&gt;long&lt;/span&gt; ClosePrinter(IntPtr hPrinter);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  41:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  42:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; PrintESC(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; type)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  43:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  44:&lt;/span&gt;             System.IntPtr lhPrinter = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; System.IntPtr();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  45:&lt;/span&gt;             DOCINFO di = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DOCINFO();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  46:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; pcWritten = 0;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  47:&lt;/span&gt;             di.pDocName = &lt;span style="color: #006080"&gt;"进退纸Document"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  48:&lt;/span&gt;             di.pDataType = &lt;span style="color: #006080"&gt;"RAW"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  49:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  50:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;try&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  51:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  52:&lt;/span&gt;                 PrintDirect.OpenPrinter(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.PrintPort, &lt;span style="color: #0000ff"&gt;ref&lt;/span&gt; lhPrinter, 0);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  53:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (lhPrinter == IntPtr.Zero)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  54:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  55:&lt;/span&gt;                     MessageBox.Show(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;"没有连接打印机或者打印机端口不是{0}！"&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.PrintPort),&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  56:&lt;/span&gt;                         &lt;span style="color: #006080"&gt;"提示"&lt;/span&gt;, MessageBoxButtons.OK, MessageBoxIcon.Error);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  57:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  58:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  59:&lt;/span&gt;                 PrintDirect.StartDocPrinter(lhPrinter, 1, &lt;span style="color: #0000ff"&gt;ref&lt;/span&gt; di);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  60:&lt;/span&gt;                 PrintDirect.StartPagePrinter(lhPrinter);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  61:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; send = &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Empty;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  62:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; j = 0; j &amp;lt; 3; j++)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  63:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  64:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;switch&lt;/span&gt; (type)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  65:&lt;/span&gt;                     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  66:&lt;/span&gt;                         &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; 0:&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  67:&lt;/span&gt;                             send = &lt;span style="color: #006080"&gt;""&lt;/span&gt; + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(27) + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(64) + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(27) + &lt;span style="color: #006080"&gt;'j'&lt;/span&gt; + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(180);&lt;span style="color: #008000"&gt;//退纸&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  68:&lt;/span&gt;                             &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  69:&lt;/span&gt;                         &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; 1:&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  70:&lt;/span&gt;                             send = &lt;span style="color: #006080"&gt;""&lt;/span&gt; + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(27) + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(64) + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(27) + &lt;span style="color: #006080"&gt;'J'&lt;/span&gt; + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(180);&lt;span style="color: #008000"&gt;//进纸&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  71:&lt;/span&gt;                             &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  72:&lt;/span&gt;                         &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; 2:&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  73:&lt;/span&gt;                             send = &lt;span style="color: #006080"&gt;""&lt;/span&gt; + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(27) + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(64) + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(12);   &lt;span style="color: #008000"&gt;//换行（未测试）&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  74:&lt;/span&gt;                             &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  75:&lt;/span&gt;                         &lt;span style="color: #0000ff"&gt;default&lt;/span&gt;:&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  76:&lt;/span&gt;                             send = &lt;span style="color: #006080"&gt;""&lt;/span&gt; + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(27) + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(64) + (&lt;span style="color: #0000ff"&gt;char&lt;/span&gt;)(12);   &lt;span style="color: #008000"&gt;//换行（未测试）&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  77:&lt;/span&gt;                             &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  78:&lt;/span&gt;                     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  79:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[] buf = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;[80];&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  80:&lt;/span&gt;                     &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; send.Length; i++)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  81:&lt;/span&gt;                     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  82:&lt;/span&gt;                         buf[i] = (&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;)send[i];&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  83:&lt;/span&gt;                     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  84:&lt;/span&gt;                     PrintDirect.WritePrinter(lhPrinter, send, send.Length, &lt;span style="color: #0000ff"&gt;ref&lt;/span&gt; pcWritten);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  85:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  86:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  87:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;catch&lt;/span&gt; (Exception e)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  88:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  89:&lt;/span&gt;                 MessageBox.Show(e.Message);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  90:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  91:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;finally&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  92:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  93:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (lhPrinter != IntPtr.Zero)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  94:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  95:&lt;/span&gt;                     PrintDirect.EndPagePrinter(lhPrinter);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  96:&lt;/span&gt;                     PrintDirect.EndDocPrinter(lhPrinter);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  97:&lt;/span&gt;                     PrintDirect.ClosePrinter(lhPrinter);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  98:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  99:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt; 100:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt; 101:&lt;/span&gt;     }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:ff00879f-be1b-42bc-925f-ac260e5090ce" &gt;标签: &lt;a href="http://technorati.com/tags/ESC%2fP" rel="tag"&gt;ESC/P&lt;/a&gt;,&lt;a href="http://technorati.com/tags/%e6%89%93%e5%8d%b0" rel="tag"&gt;打印&lt;/a&gt;,&lt;a href="http://technorati.com/tags/%e8%87%aa%e5%8a%a8%e8%bf%9b%e7%ba%b8" rel="tag"&gt;自动进纸&lt;/a&gt;,&lt;a href="http://technorati.com/tags/%e8%87%aa%e5%8a%a8%e9%80%80%e7%ba%b8" rel="tag"&gt;自动退纸&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/happyhippy/aggbug/2090468.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/happyhippy/archive/2011/06/26/2090468.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/happyhippy/archive/2011/06/21/2086441.html</id><title type="text">判断泛型的值是否为default(T)</title><summary type="text">1: public static bool IsDefault&amp;lt;T&amp;gt;(this T value) 2: { 3: //... 4: }1. ==的问题 如果用==直接判断(default(T) == value)，编译时会提示错误：Error CS0019: 运算符“==”无法应用于“T”和“T”类型的操作数 (CS0019)。2. object.Equals的问题 object提供了一个静态方...</summary><published>2011-06-21T15:00:00Z</published><updated>2011-06-21T15:00:00Z</updated><author><name>Silent Void</name><uri>http://www.cnblogs.com/happyhippy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/happyhippy/archive/2011/06/21/2086441.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/happyhippy/archive/2011/06/21/2086441.html"/><content type="html">&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt; &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; IsDefault&amp;lt;T&amp;gt;(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; T &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;) &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;       &lt;span style="color: #008000"&gt;//...&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1. ==的问题&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如果用==直接判断(default(T) == value)，编译时会提示错误：Error CS0019: 运算符“==”无法应用于“T”和“T”类型的操作数 (CS0019)。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;2. object.Equals的问题&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;object提供了一个静态方法，可用于比较两个对象是否相等：&lt;/p&gt;&#xD;
&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;&#xD;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; Equals(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; objA, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; objB)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (objA == objB)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (objA == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; || objB == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; objA.Equals(objB);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;但是该方法接收的是引用类型的实例，如果传入的是值类型(譬如int、enum、struct等)，则会对值类型进行装箱(boxing)。&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3. EqualityComparer&amp;lt;T&amp;gt;.Default.Equals&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;最给力的方法，还是用EqualityComparer&amp;lt;T&amp;gt;.Default.Equals，&lt;/p&gt;&#xD;
&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;&#xD;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; IsDefault&amp;lt;T&amp;gt;(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; T &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;) &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;      &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; EqualityComparer&amp;lt;T&amp;gt;.Default.Equals(&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;default&lt;/span&gt;(T)); &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;其实现了一个默认的比较器，可以比较Byte、Nullable&amp;lt;T&amp;gt;、Enum、Object、以及实现了IEquatable&amp;lt;T&amp;gt;接口(譬如int、bool、自定义类型等)的所有类型，可以用ILSpy来查看该类型的具体实现：&lt;/p&gt;&#xD;
&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;&#xD;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; EqualityComparer&amp;lt;T&amp;gt; defaultComparer;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; EqualityComparer&amp;lt;T&amp;gt; Default&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     [TargetedPatchingOptOut(&lt;span style="color: #006080"&gt;"Performance critical to inline across NGen image boundaries"&lt;/span&gt;), SecuritySafeCritical]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     get&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         EqualityComparer&amp;lt;T&amp;gt; equalityComparer = EqualityComparer&amp;lt;T&amp;gt;.defaultComparer;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (equalityComparer == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;             equalityComparer = EqualityComparer&amp;lt;T&amp;gt;.CreateComparer();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;             EqualityComparer&amp;lt;T&amp;gt;.defaultComparer = equalityComparer;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; equalityComparer;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt; [SecuritySafeCritical]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; EqualityComparer&amp;lt;T&amp;gt; CreateComparer()&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;     RuntimeType runtimeType = (RuntimeType)&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(T);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (runtimeType == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;byte&lt;/span&gt;))//其实byte也实现了IEquatable&amp;lt;Byte&amp;gt;，不知道为神马要把byte单独提出来？？？&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (EqualityComparer&amp;lt;T&amp;gt;)&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;font color="#ff0000"&gt;ByteEqualityComparer&lt;/font&gt;();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IEquatable&amp;lt;T&amp;gt;).IsAssignableFrom(runtimeType))&lt;font color="#ff0000"&gt;//如果类型实现了IEquatable&amp;lt;T&amp;gt;，则在运行时构造GenericEqualityComparer&amp;lt;T&amp;gt;，调用类型自身提供(重写)的equals方法。&lt;/font&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (EqualityComparer&amp;lt;T&amp;gt;)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(&lt;font color="#ff0000"&gt;GenericEqualityComparer&lt;/font&gt;&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;), runtimeType);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (runtimeType.IsGenericType &amp;amp;&amp;amp; runtimeType.GetGenericTypeDefinition() == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Nullable))&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;         RuntimeType runtimeType2 = (RuntimeType)runtimeType.GetGenericArguments()[0];&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IEquatable).MakeGenericType(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Type[]&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;             runtimeType2&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;         }).IsAssignableFrom(runtimeType2))&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (EqualityComparer&amp;lt;T&amp;gt;)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(&lt;font color="#ff0000"&gt;NullableEqualityComparer&lt;/font&gt;&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;), runtimeType2);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  39:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (runtimeType.IsEnum &amp;amp;&amp;amp; Enum.GetUnderlyingType(runtimeType) == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;))&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  40:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  41:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (EqualityComparer&amp;lt;T&amp;gt;)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(&lt;font color="#ff0000"&gt;EnumEqualityComparer&lt;/font&gt;&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;), runtimeType);&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  42:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  43:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;font color="#ff0000"&gt;ObjectEqualityComparer&lt;/font&gt;&amp;lt;T&amp;gt;();&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  44:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4. ILSpy比JustDecompile强大呀&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.1. ObjectEqualityComparer&amp;lt;T&amp;gt;.Equals方法的比较&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201106/201106212300032929.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201106/201106212300052014.png" width="757" height="309"&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201106/201106212300112293.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clip_image001" border="0" alt="clip_image001" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201106/201106212300153660.png" width="808" height="559"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;4.2. EqualityComparer&amp;lt;T&amp;gt;.CreateComparer()方法：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201106/201106212300192661.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201106/20110621230022450.png" width="1190" height="545"&gt;&lt;/a&gt; &#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;各种杯具。。。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:3080bbfb-e27a-42bd-9260-9d0e764e80e4" &gt;标签: &lt;a href="http://technorati.com/tags/default(T)" rel="tag"&gt;default(T)&lt;/a&gt;,&lt;a href="http://technorati.com/tags/IEquatable%3cT%3e" rel="tag"&gt;IEquatable&amp;lt;T&amp;gt;&lt;/a&gt;,&lt;a href="http://technorati.com/tags/EqualityCompare" rel="tag"&gt;EqualityCompare&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/happyhippy/aggbug/2086441.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/happyhippy/archive/2011/06/21/2086441.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/happyhippy/archive/2011/06/04/2072452.html</id><title type="text">T-SQL ROUND Function Bug?</title><summary type="text">先看一个例子： 1: DECLARE @Value float 2: SET @Value = 12.1785 3: SELECT &amp;#39;12.1785&amp;#39; as ValueToRound, ROUND(@Value,3) as RoundedValue 4: SET @Value = 12.1745 5: SELECT &amp;#39;12.1745&amp;#39; as ValueToRound,ROUND(@Value,3)...</summary><published>2011-06-04T00:04:00Z</published><updated>2011-06-04T00:04:00Z</updated><author><name>Silent Void</name><uri>http://www.cnblogs.com/happyhippy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/happyhippy/archive/2011/06/04/2072452.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/happyhippy/archive/2011/06/04/2072452.html"/><content type="html">&lt;p&gt;先看一个例子：&lt;/p&gt; &lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt; &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;DECLARE&lt;/span&gt; @&lt;span style="color: #0000ff"&gt;Value&lt;/span&gt; &lt;span style="color: #0000ff"&gt;float&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;SET&lt;/span&gt; @&lt;span style="color: #0000ff"&gt;Value&lt;/span&gt; = 12.1785&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;SELECT&lt;/span&gt; &lt;span style="color: #006080"&gt;'12.1785'&lt;/span&gt; &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; ValueToRound, ROUND(@&lt;span style="color: #0000ff"&gt;Value&lt;/span&gt;,3) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; RoundedValue&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;SET&lt;/span&gt; @&lt;span style="color: #0000ff"&gt;Value&lt;/span&gt; = 12.1745&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;SELECT&lt;/span&gt; &lt;span style="color: #006080"&gt;'12.1745'&lt;/span&gt; &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; ValueToRound,ROUND(@&lt;span style="color: #0000ff"&gt;Value&lt;/span&gt;,3) &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; RoundedValue &lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;猜猜看，结果是多少？这个例子源自：&lt;a href="http://connect.microsoft.com/wf/feedback/details/301942/t-sql-round-function-bug" target="_blank"&gt;T-SQL ROUND Function Bug&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1. 问题起因&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;一个老系统，每个月要对系统发生的每笔业务数据进行汇总，生成应收款；但是每个月累计下来，总会与每天的连续累加汇总差(相差几分钱，或者几毛钱)。&lt;/p&gt;&#xD;
&lt;p&gt;同样的问题还有：仓库里面一批按重量计数的物资，每次出库的时候销账；但偶尔会出现：需要出库的数量，与库存中现有数量一致，但依然无法出库的情况。&lt;/p&gt;&#xD;
&lt;p&gt;问题的根源，就在于数据的存储类型。系统中，选择了使用float来存储数据。但计算机中，是使用近似值来表示float/double的，在这种+/-过程中，误差不断地累积，就出现了上述的这些问题。关于浮点数的存储格式，可以参考我之前的文章：&lt;a href="http://www.cnblogs.com/happyhippy/archive/2006/11/18/601223.html"&gt;“精确”判断一个浮点数是否等于0&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;2. Linq to SQL中的Round&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;知道了问题的原因，我们就可以针对性地进行处理：对数据进行四舍五入后再进行求和。&lt;/p&gt;&#xD;
&lt;p&gt;C#中，提供了两种控制四舍五入的计算方式：MidpointRounding.ToEven和MidpointRounding.AwayFromZero；默认为MidpointRounding.ToEven，即当一个数字是其他两个数字的中间值时，会将其舍入为最接近的偶数。有关舍入方式，可以参考MSDN：“&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.midpointrounding.aspx" target="_blank"&gt;MidpointRounding 枚举&lt;/a&gt;”。&lt;/p&gt;&#xD;
&lt;p&gt;值得一提的是，里面对MidpointRounding.AwayFromZero的翻译有误，翻译原文为：“AwayFromZero 当一个数字是其他两个数字的中间值时，会将其舍入为两个值中绝对值较小的值。”但英文原文为：“When a number is halfway between two others, it is rounded toward the nearest number that is away from zero.” 文档描述得相当糟糕，不知道是不是我理解能力太差，反正那一坨东西，绕来绕去，还是看里面举的例子比较靠谱。&lt;/p&gt;&#xD;
&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;&#xD;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;// 3.4 = Math.Round( 3.45, 1)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000"&gt;//-3.4 = Math.Round(-3.45, 1)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #008000"&gt;// 3.4 = Math.Round( 3.45, 1, MidpointRounding.ToEven)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #008000"&gt;// 3.5 = Math.Round( 3.45, 1, MidpointRounding.AwayFromZero)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; &lt;span style="color: #008000"&gt;//-3.4 = Math.Round(-3.45, 1, MidpointRounding.ToEven)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; //-3.5 = Math.Round(-3.45, 1, MidpointRounding.AwayFromZero)&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;L2S中，如果直接用Math.Round(T.Amount, 2, MidpointRounding.AwayFromZero)，则解析成T-SQL就是直接调用Round函数；如果用Math.Round(T.Amount, 2, MidpointRounding.ToEven)，则会解析为：&lt;/p&gt;&#xD;
&lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt;&#xD;
&lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;CASE&lt;/span&gt; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;WHEN&lt;/span&gt; ((([t0].[Amount]) * 2) = round(([t0].[Amount]) * 2, 2)) &lt;span style="color: #0000ff"&gt;AND&lt;/span&gt; (([t0].[Amount]) &amp;lt;&amp;gt; round([t0].[Amount], 2)) &lt;span style="color: #0000ff"&gt;THEN&lt;/span&gt; round(([t0].[Amount]) / 2, 2) * 2&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;ELSE&lt;/span&gt; round([t0].[Amount], 2)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;END&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3. 解决方法&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3.1 两次Round&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;使用一次Round可以解决小数点取舍问题，但无法处理浮点数精度带来的误差，下面是一次Round带来的结果：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201106/201106040803369572.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201106/201106040803373094.png" width="245" height="399"&gt;&lt;/a&gt; &#xD;
&lt;p&gt;这是因为，譬如浮点数2053.345在计算机内部存储的格式可能为2053.2449999999……，一次Round的结果就直接把后面49999…..的给舍掉了。但我们可以使用两次Round来达到需要的舍入效果：Round(Round(Value, 6), 2)&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201106/201106040803375536.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201106/201106040803378011.png" width="248" height="390"&gt;&lt;/a&gt; &#xD;
&lt;p&gt;&lt;strong&gt;3.2 Decimal&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;处理精度问题，将数据类型定义为Decimal才是王道。&lt;/p&gt;&#xD;
&lt;p&gt;Decimal在计算及中的存储格式：Decimal 值长度是128位，由 1 位符号、96 位整数以及比例因子组成，比例因子用作 96 位整数的除数并指定整数的哪一部分为小数。比例因子隐式地定为数字 10 的幂，指数范围从 0 到 28。因此，Decimal 值的二进制表示形式为：((-2^96 到 2^96) / 10^(0 到 28))。比例因子还保留 Decimal 数字中的所有尾数零。&lt;/p&gt;&#xD;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:51709b94-a258-4102-8c6a-bc661e722b15" &gt;标签: &lt;a href="http://technorati.com/tags/Round" rel="tag"&gt;Round&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Decimal" rel="tag"&gt;Decimal&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Linq+to+Sql" rel="tag"&gt;Linq to Sql&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/happyhippy/aggbug/2072452.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/happyhippy/archive/2011/06/04/2072452.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/happyhippy/archive/2011/05/28/2060553.html</id><title type="text">T-SQL 根据年月日创建DateTime</title><summary type="text">T-SQL中提供了不少操作DateTime的函数，可惜竟然没有根据年月日创建DateTime类型的函数，例如DateTime(yyyy, MM, dd)这样的“构造函数”，杯具啊~~ 1: DECLARE @Year int, @Month int, @Day int; 2: SELECT @Year=2011, @Month=5, @Day=8; 3: 4: --法1： 5: SELECT C...</summary><published>2011-05-28T02:36:00Z</published><updated>2011-05-28T02:36:00Z</updated><author><name>Silent Void</name><uri>http://www.cnblogs.com/happyhippy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/happyhippy/archive/2011/05/28/2060553.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/happyhippy/archive/2011/05/28/2060553.html"/><content type="html">&lt;p&gt;T-SQL中提供了不少操作DateTime的函数，可惜竟然没有根据年月日创建DateTime类型的函数，例如DateTime(yyyy, MM, dd)这样的“构造函数”，杯具啊~~&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, 'Courier New', courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px"&gt; &lt;div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;DECLARE&lt;/span&gt; @&lt;span style="color: #0000ff"&gt;Year&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, @&lt;span style="color: #0000ff"&gt;Month&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;, @&lt;span style="color: #0000ff"&gt;Day&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;SELECT&lt;/span&gt; @&lt;span style="color: #0000ff"&gt;Year&lt;/span&gt;=2011, @&lt;span style="color: #0000ff"&gt;Month&lt;/span&gt;=5, @&lt;span style="color: #0000ff"&gt;Day&lt;/span&gt;=8;&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; --法1：&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;SELECT&lt;/span&gt; &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(&lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(@&lt;span style="color: #0000ff"&gt;Year&lt;/span&gt; &lt;span style="color: #0000ff"&gt;AS&lt;/span&gt; &lt;span style="color: #0000ff"&gt;varchar&lt;/span&gt;(4)) + &lt;span style="color: #006080"&gt;'-'&lt;/span&gt; + &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(@&lt;span style="color: #0000ff"&gt;Month&lt;/span&gt; &lt;span style="color: #0000ff"&gt;AS&lt;/span&gt; nvarchar(2)) + &lt;span style="color: #006080"&gt;'-'&lt;/span&gt; + &lt;span style="color: #0000ff"&gt;CAST&lt;/span&gt;(@&lt;span style="color: #0000ff"&gt;Day&lt;/span&gt; &lt;span style="color: #0000ff"&gt;AS&lt;/span&gt; nvarchar(2)) &lt;span style="color: #0000ff"&gt;AS&lt;/span&gt; DateTime)&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; --法2：&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;SELECT&lt;/span&gt; DateAdd(dd, @&lt;span style="color: #0000ff"&gt;Day&lt;/span&gt;-1, DateAdd(mm, @&lt;span style="color: #0000ff"&gt;Month&lt;/span&gt; -1, DateAdd(yy, @&lt;span style="color: #0000ff"&gt;Year&lt;/span&gt; - 1900, &lt;span style="color: #006080"&gt;'19000101'&lt;/span&gt;)))&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt; --法3：&lt;/pre&gt;&lt;pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, 'Courier New', courier, monospace; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;SELECT&lt;/span&gt; DateAdd(mm, (@&lt;span style="color: #0000ff"&gt;Year&lt;/span&gt; - 1900) * 12 + @&lt;span style="color: #0000ff"&gt;Month&lt;/span&gt; - 1 , @&lt;span style="color: #0000ff"&gt;Day&lt;/span&gt; - 1)&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:75eb5d55-8eee-4051-b072-1265ba74ce0d" &gt;标签: &lt;a href="http://technorati.com/tags/DateTime" rel="tag"&gt;DateTime&lt;/a&gt;,&lt;a href="http://technorati.com/tags/%e6%9e%84%e9%80%a0%e5%87%bd%e6%95%b0" rel="tag"&gt;构造函数&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/happyhippy/aggbug/2060553.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/happyhippy/archive/2011/05/28/2060553.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/happyhippy/archive/2011/01/29/1947443.html</id><title type="text">使用键值表实现通用流水号</title><summary type="text">一般的简单的流水号，由标识+日期+自增序号来组成；但如果考虑通用的话，就稍微复杂点儿的，需要考虑自定义日期格式、自增序号归1、自增序号溢出处理、前缀/中缀/后缀、并发访问、批量获取等，本文抽象出一个通用的生成流水号的方案。1. 查询原始数据表 vs. 键值表2. 键值表、取流水号的T-SQL实现3. 并发处理需要考虑的三个因素4. C#封装取流水号操作5. 不给代码怎马叫给力~</summary><published>2011-01-29T05:13:00Z</published><updated>2011-01-29T05:13:00Z</updated><author><name>Silent Void</name><uri>http://www.cnblogs.com/happyhippy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/happyhippy/archive/2011/01/29/1947443.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/happyhippy/archive/2011/01/29/1947443.html"/><content type="html">&lt;p&gt;很多MIS系统，都需要用到流水号；一般的简单的流水号，由标识+日期+自增序号来组成；但如果考虑通用的话，就稍微复杂点儿的，需要考虑自定义日期格式、自增序号归1、自增序号溢出处理、前缀/中缀/后缀、并发访问、批量获取等，本文抽象出一个通用的生成流水号的方案。&lt;/p&gt; &lt;p&gt;1. 查询原始数据表 vs. 键值表&lt;br /&gt;2. 键值表、取流水号的T-SQL实现&lt;br /&gt;3. 并发处理需要考虑的三个因素&lt;br /&gt;4. C#封装取流水号操作&lt;br /&gt;5. 不给代码怎马叫给力~&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;1. 查询原始数据表 vs. 键值表&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;流水号的变动部分可分为日期和自增序号两部分，日期就是取当前的日期(yyyy、yyMM、或yyyyMMdd等)，自增序号部分可以有如下两种获取方式：&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;strong&gt;1.1. 每次查询原始数据表&lt;/strong&gt;：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;缺点就是要手工&lt;strong&gt;处理并发，如果并发量大的话，性能堪忧&lt;/strong&gt;；好处就是每次可以取得准确的下一个自增序号，如果最后没有保存或者保存失败，取得的序号&lt;strong&gt;可以被重复读得，不会被浪费&lt;/strong&gt;。&lt;/p&gt; &lt;p&gt;下面是一个并发示例：譬如当前表中最大的序号(这里暂时只考虑自增序号部分，忽略日期)为003，这是A/B两个用户同时打开页面并取得流水号，此时数据都没有保存，因此他们会取得相同的流水号004，保存时就会出现重复键值(违反唯一性约束)了。保险一点的做法，就是在保存的时候，去校验一下流水号是否已经被用过了；但是校验的时候，也必须十分小心，下面是一个保存时的未考虑并发的&lt;strong&gt;无效校验&lt;/strong&gt;：&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312065370.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312099047.png" border="0" width="800" height="454" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;针对这个问题，一种解决办法就是，&lt;strong&gt;将操作串行化，保存前先获得锁&lt;/strong&gt;：&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312117883.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312146785.png" border="0" width="801" height="404" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;可以在应用程序中加锁(但如果有集群的话，还要考虑多个服务器的问题)，或者锁数据库表。虽然加锁能解决并发问题，但是却带来更严重的性能问题。&lt;strong&gt;每次获取流水号时都要去查询原始数据表(或索引，如果有索引的话)，且插入前要进行加锁，操作只能被串行化，并发量一大，性能是个大问题&lt;/strong&gt;。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1.2. 使用键值表&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;另一种思路就是使用键值表。可以为每个需要使用流水号的表，在键值表中保存一条记录，该记录保存其对应表中当前的最大流水号值。这样的操作的好处是：每次取流水号的时候，只需要操作该表中对应的一条记录即可，而不用去查询原始表/索引；还可以用于批量操作，一次获取一批流水号(批量录入或导入的时候，经常会用到)。&lt;/p&gt; &lt;p&gt;键值表还需要处理的一个问题，何时更新键值表中的记录(当前最大值)？有两种处理思路：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (1). &lt;strong&gt;采用写时更新&lt;/strong&gt;：能避免每次读取时查询原始表的问题，但还是会遇到上面1.1节中的并发问题。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (2). &lt;strong&gt;每次读取最大值的时候更新&lt;/strong&gt;：&lt;strong&gt;先锁记录再读&lt;/strong&gt;，最后更新为新的最大值。下一个人来读的时候，再取到下一个流水号，这样可以获得最大的并发性，但带来的问题是，如果上一个人取到的业务流水号最后没有保存，则这个流水号就废了(跳过去了)，导致最后的实际的业务流水号不连续。如果业务上允许序号被浪费，建议采用这种方式。&lt;/p&gt; &lt;p&gt;本文的解决方案，也主要是针对后一种(读取时更新)获取流水号的方式。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;2. 键值表、取流水号的T-SQL实现&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;还虑通用型，可以对业务流水号进行抽象：&lt;strong&gt;流水号 = 前缀+日期+中缀+流水号+后缀&lt;/strong&gt;。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其中：&lt;br /&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 前缀/中缀/后缀：可以包含0个或多个字符；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 日期：可以包含yyMM、yyyy、yyMMdd、yyyyMMdd等多种格式；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 流水号：从1开始累加，按日期归1，长度可扩展(考虑到溢出)；&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这些信息都可以放在键值表中统一维护。&lt;/p&gt; &lt;p&gt;继续考虑通用性，可以封装下取流水号的操作，提供一个&lt;strong&gt;批量获取&lt;/strong&gt;方式，一次取一批序号(Max + N)，避免批量操作时循环去取(Max + 1)；批量录入或导入的时候，经常会用到批量获取的方式。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2.1 键值表的设计&lt;/strong&gt;&lt;/p&gt; &lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt; &lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; /*happyhippy.cnblogs.com*/ &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;IF&lt;/span&gt;(OBJECT_ID(&lt;span style="color: #006080;"&gt;'SequenceNumber'&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;IS&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;NOT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;NULL&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;DROP&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;TABLE&lt;/span&gt; SequenceNumber;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Create&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;Table&lt;/span&gt; SequenceNumber&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt; (&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;     ID &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;identity&lt;/span&gt;(1,1),&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;     Code nvarchar(10) &lt;font size="2"&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;&lt;span style="color: #0000ff;"&gt;primary&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;key&lt;/span&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/font&gt;,    /*&lt;span style="color: #0000ff;"&gt;Key&lt;/span&gt;*/&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;Prefix&lt;/span&gt; nvarchar(5),   /*前缀*/&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;     DateType nvarchar(8), /*日期类型，可以为yyyy，yymm, yyyymm，yymmdd，yyyymmdd等等等等。*/&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;     Infix nvarchar(5),    /*中缀*/&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt;     IndexLength &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;,      /*自增流水号长度*/&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;     Suffix nvarchar(5),   /*后缀*/&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;     MaxDate nvarchar(8),  /*当前最大日期值*/&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;     MaxIndex &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;default&lt;/span&gt;(0),/*当前最大流水号值*/&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;     CurrentMaxValue &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;Prefix&lt;/span&gt; + MaxDate + Infix + Replace(STR(MaxIndex, IndexLength), &lt;span style="color: #006080;"&gt;' '&lt;/span&gt; , &lt;span style="color: #006080;"&gt;'0'&lt;/span&gt;) + Suffix)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt; )&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;注意：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (1). 表的主键设置在Code字段上；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (2). MaxData、MaxIndex等记录当前最大值，用于直接运算。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2.2 T-SQL获取流水号&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; /*happyhippy.cnblogs.com*/&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;go&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;IF&lt;/span&gt;(OBJECT_ID(&lt;span style="color: #006080;"&gt;'GetSequenceNumber'&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;IS&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;NOT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;NULL&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;DROP&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;PROCEDURE&lt;/span&gt;  GetSequenceNumber;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;     &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;go&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;CREATE&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;PROCEDURE&lt;/span&gt; GetSequenceNumber&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt; (&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt;     @Code nvarchar(10),&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;     @&lt;span style="color: #0000ff;"&gt;Count&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; = 1&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt; )&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;AS&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;BEGIN&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;DECLARE&lt;/span&gt; @NewValue nvarchar(20), @CurrentDate nvarchar(8);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;DECLARE&lt;/span&gt; @&lt;span style="color: #0000ff;"&gt;Prefix&lt;/span&gt; nvarchar(5), @DateType nvarchar(8), @Infix nvarchar(5), @Suffix nvarchar(5);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;DECLARE&lt;/span&gt; @MaxIndex &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;, @IndexLength tinyint, @MaxDate nvarchar(8);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;BEGIN&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;TRAN&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  19:&lt;/span&gt;         --读取配置信息&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  20:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;SELECT&lt;/span&gt;  @&lt;span style="color: #0000ff;"&gt;Prefix&lt;/span&gt; = &lt;span style="color: #0000ff;"&gt;Prefix&lt;/span&gt;, @Infix = Infix, @Suffix = Suffix,&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  21:&lt;/span&gt;                 @DateType = DateType, @MaxDate=MaxDate,&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  22:&lt;/span&gt;                 @MaxIndex = MaxIndex, @IndexLength = IndexLength&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  23:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;FROM&lt;/span&gt; SequenceNumber &lt;span style="color: #0000ff;"&gt;with&lt;/span&gt;&lt;font color="#ff0000" size="4"&gt;&lt;strong&gt;(xlock)&lt;/strong&gt;&lt;/font&gt; &lt;span style="color: #0000ff;"&gt;WHERE&lt;/span&gt; Code=@Code;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  24:&lt;/span&gt;         &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  25:&lt;/span&gt;         --取得日期部分，如果需要其他格式，需要自己再扩展，增加CASE分支。&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  26:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;SET&lt;/span&gt; @CurrentDate= &lt;span style="color: #0000ff;"&gt;SUBSTRING&lt;/span&gt;(&lt;span style="color: #0000ff;"&gt;Convert&lt;/span&gt;(nvarchar(8), GetDate(), 112),&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  27:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;CASE&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;SubString&lt;/span&gt;(@DateType, 1, 4)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  28:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;WHEN&lt;/span&gt; &lt;span style="color: #006080;"&gt;'yyyy'&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;THEN&lt;/span&gt; 1&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  29:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;WHEN&lt;/span&gt; &lt;span style="color: #006080;"&gt;'yyy'&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;THEN&lt;/span&gt; 2&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  30:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;ELSE&lt;/span&gt; 3&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  31:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;END&lt;/span&gt;, LEN(@DateType));&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  32:&lt;/span&gt;         &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  33:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;IF&lt;/span&gt;(@CurrentDate = @MaxDate)            &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  34:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;SET&lt;/span&gt; @MaxIndex = @MaxIndex + @&lt;span style="color: #0000ff;"&gt;Count&lt;/span&gt;; --累加&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  35:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;ELSE&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  36:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;SET&lt;/span&gt; @MaxIndex = @&lt;span style="color: #0000ff;"&gt;Count&lt;/span&gt;; --归1&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  37:&lt;/span&gt;         &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  38:&lt;/span&gt;         &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  39:&lt;/span&gt;         --超过自增长度限制，自动扩展自增部分的长度&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  40:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;IF&lt;/span&gt;(@MaxIndex &amp;gt;= POWER(10, @IndexLength)) &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  41:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;SET&lt;/span&gt; @IndexLength = @IndexLength + 1; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  42:&lt;/span&gt;         &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  43:&lt;/span&gt;         --可以取消下面一行的注释，来测试并发&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  44:&lt;/span&gt;         --&lt;span style="color: #0000ff;"&gt;Waitfor&lt;/span&gt; delay &lt;span style="color: #006080;"&gt;'00:00:10'&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  45:&lt;/span&gt;             &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  46:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;Update&lt;/span&gt; SequenceNumber &lt;span style="color: #0000ff;"&gt;SET&lt;/span&gt; MaxDate = @CurrentDate, MaxIndex=@MaxIndex, IndexLength=@IndexLength &lt;span style="color: #0000ff;"&gt;WHERE&lt;/span&gt; Code=@Code;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  47:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;COMMIT&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;TRAN&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  48:&lt;/span&gt;     &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  49:&lt;/span&gt;     --取得获取到的最大值，取得@IndexLength和Len(@Suffix)用于解析得到批量获取的序列号&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  50:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;SELECT&lt;/span&gt; (@&lt;span style="color: #0000ff;"&gt;Prefix&lt;/span&gt; + @CurrentDate + @Infix + Replace(STR(@MaxIndex, @IndexLength), &lt;span style="color: #006080;"&gt;' '&lt;/span&gt; , &lt;span style="color: #006080;"&gt;'0'&lt;/span&gt;) + @Suffix), @IndexLength, Len(@Suffix);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  51:&lt;/span&gt; END&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;注意：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (1). 整个读取、更新过程，封装在一次事务操作中；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (2) 参数@Count，可以传一个正整数，批量获取多个流水号；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (3). 第19~22行，读取的时候获取排它锁(xlock)，用于处理并发情况；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (4). 第39~41行，如果溢出，则自动扩展自增序号的宽度；&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3. 并发需要考虑的几个因素&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;并发要考虑两种情况：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (1) 并发访问&lt;strong&gt;同一种类&lt;/strong&gt;的序列号(键值表中的一个Key)时，必须&lt;strong&gt;串行访问&lt;/strong&gt;，以防止取得相同的流水号；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (2) 并发访问&lt;strong&gt;不同种类&lt;/strong&gt;的序列号(键值表中的不同Key)时，必须允许&lt;strong&gt;并发访问&lt;/strong&gt;，互不干扰才能获得最大的并发度；&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3.1 在应用程序中处理锁，还是在数据库中处理锁？&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;.Net中提供了现成lock、Monitor等，我们可以用来处理锁；譬如可以维护一个字典Dictionary&amp;lt;string, Object&amp;gt;，Key中保存键值表中对应的键值，Value保存同步对象，伪代码如下：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; dictionarySyncObj = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&amp;gt; syncDictionary = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; GetMaxSequenceNumber(&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; key)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;lock&lt;/span&gt; (dictionarySyncObj)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!syncDictionary.ContainsKey(key))&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt;             syncDictionary.Add(key, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;());&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt;     Object keySyncObj = syncDictionary[key];&lt;span style="color: #008000;"&gt;//针对不同的Key，使用不同的同步对象&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;lock&lt;/span&gt; (keySyncObj)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;         &lt;span style="color: #008000;"&gt;//从数据库读取最大流水号....&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; ....&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;程序中所有需要取流水号的地方，都调用该函数来获取，以保证对同一种类序列号的访问被串行化。如果系统只是部署在单台服务器上，这种方法没有问题；但是如果使用了服务器集群，系统在多个系统上部署了多份，则还是无法串行化对同一个Key的所有访问。&lt;/p&gt;&#xD;
&lt;p&gt;比较理想的做法，是在一个统一的地方处理并发，譬如在数据库中。上面第2节中，给出的键值表实现和获取流水号的存储过程，其实已经实现了并发处理，下面展开进行讨论。讨论之前，先执行下列代码来构造几个测试用例：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000;"&gt;/*构造测试用例*/&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; INSERT INTO SequenceNumber(Code, Prefix, DateType, Infix, IndexLength, Suffix)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt;     VALUES(&lt;span style="color: #006080;"&gt;'Test1'&lt;/span&gt;, &lt;span style="color: #006080;"&gt;'P'&lt;/span&gt;, &lt;span style="color: #006080;"&gt;'yyyy'&lt;/span&gt;, &lt;span style="color: #006080;"&gt;''&lt;/span&gt;, 8, &lt;span style="color: #006080;"&gt;''&lt;/span&gt;),&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt;         (&lt;span style="color: #006080;"&gt;'Test2'&lt;/span&gt;, &lt;span style="color: #006080;"&gt;''&lt;/span&gt;, &lt;span style="color: #006080;"&gt;'yymmdd'&lt;/span&gt;, &lt;span style="color: #006080;"&gt;'M'&lt;/span&gt;, 6, &lt;span style="color: #006080;"&gt;''&lt;/span&gt;),&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;         (&lt;span style="color: #006080;"&gt;'Test3'&lt;/span&gt;, &lt;span style="color: #006080;"&gt;'P'&lt;/span&gt;, &lt;span style="color: #006080;"&gt;'yymmdd'&lt;/span&gt;, &lt;span style="color: #006080;"&gt;'M'&lt;/span&gt;, 6, &lt;span style="color: #006080;"&gt;'S'&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt; UPDATE SequenceNumber SET MaxDate= SUBSTRING(Convert(nvarchar(8), GetDate(), 112),&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;             CASE SubString(DateType, 1, 4)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt;                 WHEN &lt;span style="color: #006080;"&gt;'yyyy'&lt;/span&gt; THEN 1&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;                 WHEN &lt;span style="color: #006080;"&gt;'yyy'&lt;/span&gt; THEN 2&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;                 ELSE 3&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt;             END, LEN(DateType));&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp; 3.2 串行化访问&lt;strong&gt;同一种类&lt;/strong&gt;的序列号&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;默认情况下(Read Committed事务隔离级别)，读取操作会对对应的数据Key(或行)加S锁(不考虑锁升级的情况)，对该行所属的页和表加IS锁；读取完毕后，就释放这些IS锁和S锁。可以加表提示(with (holdlock))，来让会话强制持有锁，直至事务结束(提交或回滚)后才释放锁。但是，如果多个会话并发访问的时候，由于IS锁与IS锁之间是兼容的，在值被更新(持有更新锁ulock)之前，可以并发读得相同的数据，因此这里&lt;strong&gt;读取时，必须要用排它锁(xlock)来独占资源，当一个线程读的时候，不允许其他线程并发读&lt;/strong&gt;。有关并发和锁兼容性的更多介绍，可以参考我之前的文章《&lt;a href="http://www.cnblogs.com/happyhippy/archive/2008/11/14/1333922.html"&gt;SQL Server死锁总结&lt;/a&gt;》。&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;可以取消2.2节中存储过程&lt;span style="color: #006080;"&gt;GetSequenceNumber&lt;/span&gt;中的第44行(Waitfor delay '00:00:10';)的注释，让T-SQL执行时等待10秒钟，以比较测试结果。&lt;strong&gt;开两个窗口&lt;/strong&gt;分别&lt;strong&gt;同时执行&lt;/strong&gt;下列一段测试代码：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;exec&lt;/span&gt; dbo.GetSequenceNumber &lt;span style="color: #006080;"&gt;'Test2'&lt;/span&gt;, 1;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;第一个窗口的执行结果：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312169491.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312171019.png" border="0" width="775" height="197" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;第二个窗口的执行结果(操作过程中存在延时，所以显示的只有18秒)：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312195677.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312204381.png" border="0" width="786" height="207" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;虽然两个会话&amp;#8220;&lt;strong&gt;同时&lt;/strong&gt;&amp;#8221;执行(第二个会话，我在操作时存在延时，所以显示的只有18秒)，但两个会话没有读得相同的序列号。执行时，第二个会话等待被阻塞等待了；只有等到第一个会话执行完毕后，第二个会话才获得锁资源，并继续执行；因此用了2倍的时间(20秒)。这就达到了多线程访问同一个Key时必须被串行化的效果。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp; 3.3 并发访问&lt;strong&gt;不同种类&lt;/strong&gt;的序列号&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;多线程并发访问&lt;strong&gt;不同种类&lt;/strong&gt;的序列号(键值表中的不同Key)时，必须允许&lt;strong&gt;并发访问&lt;/strong&gt;，互不干扰才能获得最大的并发度。在2.1节键值表的设计中，我将Code设为主键，这样做的一个好处，就是在读取一条Code记录并获取锁的时候，锁的粒度只会限制在Key锁，而不会升级为页锁或表锁。&lt;/p&gt;&#xD;
&lt;p&gt;现在开两个查询窗口，分别&lt;strong&gt;同时执行&lt;/strong&gt;下列两段代码（注意：这次，两个窗口访问的是不同的Key）：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;exec&lt;/span&gt; dbo.GetSequenceNumber &lt;span style="color: #006080;"&gt;'Test2'&lt;/span&gt;, 1;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;exec&lt;/span&gt; dbo.GetSequenceNumber &lt;span style="color: #006080;"&gt;'Test3'&lt;/span&gt;, 1;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;第一个窗口的执行结果：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312226531.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312235234.png" border="0" width="773" height="201" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;第二个窗口的执行结果：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/20110129131225731.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312263023.png" border="0" width="780" height="184" /&gt;&lt;/a&gt; &#xD;
&lt;/p&gt;&lt;p&gt;虽然两个会话同时执行，但是第二个会话，并没有被第一个会话阻塞，所以第二个会话也只用10秒就执行完毕了。两个会话可以并发执行，这就达到了多线程可以并发访问不同Key的效果。 &#xD;
&lt;/p&gt;&lt;p&gt;如果执行上面的查询时，我们sp_lock来查看锁的情况，也可以看到： &#xD;
&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312295305.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101291312316899.png" border="0" width="848" height="416" /&gt;&lt;/a&gt; &#xD;
&lt;/p&gt;&lt;p&gt;参考我之前的文章《&lt;a href="http://www.cnblogs.com/happyhippy/archive/2008/11/14/1333922.html"&gt;SQL Server死锁总结&lt;/a&gt;》，并结合上图，可以看到，两个X锁是应用在不同的Resource上，他们之间不会冲突；IX锁虽然应用在同一个Table上/Page(1:828)上，但IX锁与IX锁之间是兼容的，他们之间也不存在冲突；因此多个线程之间不会相互影响。回过头来考虑3.2节中的测试，两个会话尝试对同一个Key加X锁，但X锁与X锁之间是不兼容的，因此读取操作被串行化了。这里利用SQL Server的锁机制来实现并行化/串行化的目的。&lt;/p&gt;&#xD;
&lt;p&gt;抛一个问题，如果键值表的主键，不在Code字段上，还能并发访问&lt;strong&gt;不同种类&lt;/strong&gt;的序列号吗？有兴趣的可以试试。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4. C#封装取流水号操作&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; ReadOnlyCollection&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&amp;gt; GetSequenceNumbers(SequenceType type, &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; count = 1)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; maxSequenceNumber = &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;.Empty;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;byte&lt;/span&gt; indexLength = 0;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;byte&lt;/span&gt; suffixLength = 0;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;//以上三个值，调用存储过程读取，省略。。。。&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;     &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (count == 1)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; List&amp;lt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&amp;gt;() { maxSequenceNumber }).AsReadOnly();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; prefix = maxSequenceNumber.Substring(0, maxSequenceNumber.Length - indexLength - suffixLength);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; index = Convert.ToInt32(maxSequenceNumber.Substring(prefix.Length, indexLength));&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; suffix = maxSequenceNumber.Substring(maxSequenceNumber.Length - suffixLength);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; format = &lt;span style="color: #006080;"&gt;"0000000000"&lt;/span&gt;.Substring(0, indexLength);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  19:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; Enumerable.Range(index - count + 1, count)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  20:&lt;/span&gt;                     .Select(i =&amp;gt; prefix + i.ToString(format) + suffix)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  21:&lt;/span&gt;                     .ToList()&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  22:&lt;/span&gt;                     .AsReadOnly();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  23:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  24:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;使用方式：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; item &lt;span style="color: #0000ff;"&gt;in&lt;/span&gt; SequenceNumber.GetSequenceNumbers(SequenceType.Test3, 3))&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt;    Response.Write(item + &lt;span style="color: #006080;"&gt;"&amp;lt;br/&amp;gt;"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;5. 不给代码怎马叫给力~&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://files.cnblogs.com/happyhippy/happyhippy.cnblogs.com.SequenceNumber.rar"&gt;happyhippy.cnblogs.com.SequenceNumber.rar&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;参考文献：&lt;br /&gt;《企业应用架构模式》&lt;/p&gt;&lt;img src="http://www.cnblogs.com/happyhippy/aggbug/1947443.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/happyhippy/archive/2011/01/29/1947443.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/happyhippy/archive/2011/01/12/1934006.html</id><title type="text">[SilverLight]DataGrid实现批量输入(like Excel)（补充）</title><summary type="text">1. Tab/Enter跳转到下一列；2. 最后一行最后一列，Tab/Enter自动增加新行；3. 增加新行后，自动跳转到新增行的第一列；4. 删除行后，自动选中上一行；5. Up/Down/Left/Right自动编辑；</summary><published>2011-01-12T12:33:00Z</published><updated>2011-01-12T12:33:00Z</updated><author><name>Silent Void</name><uri>http://www.cnblogs.com/happyhippy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/happyhippy/archive/2011/01/12/1934006.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/happyhippy/archive/2011/01/12/1934006.html"/><content type="html">&lt;p&gt;更新内容：&lt;/p&gt; &lt;p&gt;1. Tab/Enter跳转到下一列；&lt;br /&gt;2. 最后一行最后一列，Tab/Enter自动增加新行；&lt;br /&gt;3. 增加新行后，自动跳转到新增行的第一列；&lt;br /&gt;4. 删除行后，自动选中上一行；&lt;br /&gt;5. Up/Down/Left/Right自动编辑；&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;实现方式：&lt;/p&gt; &lt;p&gt;&lt;strong&gt;1. Tab/Enter跳转到下一列&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;从google搜到的一篇文章《&lt;a href="http://forums.silverlight.net/forums/p/206694/485086.aspx" target="_blank"&gt;Datagrid cell navigation with enter key&lt;/a&gt;》，文中最开始提到在DataGrid的KeyDown事件中进行处理。但是DataGrid里面做了一些封装，我们在自己注册(通过+=操作符来登记、或者XAML中定义)的KeyDown事件中，截获不到Enter/Tab等键。所以最后原作者有提出一个思路：继承DataGrid，重新OnKeyDown方法。&lt;/p&gt; &lt;p&gt;但我之前的思路，是通过扩展方法来扩展DataGrid，再来重写就有点儿郁闷了。于是找出Reflector，翻了下DataGrid的实现(reflector中copy出来的)：&lt;/p&gt; &lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt; &lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000;"&gt;// happyhippy.cnblogs.com&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000;"&gt;// 构造函数&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; DataGrid()&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;//省略&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;.KeyDown += &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; KeyEventHandler(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.DataGrid_KeyDown);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;.KeyUp += &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; KeyEventHandler(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.DataGrid_KeyUp);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;//省略&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; DataGrid_KeyDown(&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; sender, KeyEventArgs e)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!e.Handled)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;         e.Handled = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessDataGridKey(e);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  19:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; ProcessDataGridKey(KeyEventArgs e)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  20:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  21:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; flag = &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  22:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;switch&lt;/span&gt; (e.Key)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  23:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  24:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Tab:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  25:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessTabKey(e);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  26:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  27:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Enter:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  28:&lt;/span&gt;             flag = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessEnterKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  29:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  30:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  31:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Escape:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  32:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessEscapeKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  33:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  34:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.PageUp:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  35:&lt;/span&gt;             flag = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessPriorKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  36:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  37:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  38:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.PageDown:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  39:&lt;/span&gt;             flag = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessNextKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  40:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  41:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  42:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.End:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  43:&lt;/span&gt;             flag = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessEndKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  44:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  45:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  46:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Home:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  47:&lt;/span&gt;             flag = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessHomeKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  48:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  49:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  50:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Left:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  51:&lt;/span&gt;             flag = (&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;.FlowDirection == FlowDirection.LeftToRight) ? &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessLeftKey() : &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessRightKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  52:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  53:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  54:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Up:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  55:&lt;/span&gt;             flag = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessUpKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  56:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  57:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  58:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Right:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  59:&lt;/span&gt;             flag = (&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;.FlowDirection == FlowDirection.LeftToRight) ? &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessRightKey() : &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessLeftKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  60:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  61:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  62:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Down:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  63:&lt;/span&gt;             flag = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessDownKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  64:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  65:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  66:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Insert:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  67:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessCopyKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  68:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  69:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.A:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  70:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessAKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  71:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  72:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.C:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  73:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessCopyKey();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  74:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  75:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.F2:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  76:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ProcessF2Key(e);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  77:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  78:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (flag &amp;amp;&amp;amp; &lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;.IsTabStop)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  79:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  80:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;.Focus();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  81:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  82:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; flag;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  83:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;我们可以发现，KeyDown中已经定义一部分按键的处理，并更新了KeyEventArgs.Handled属性。MSDN对该属性的解释是：&lt;/p&gt;&#xD;
&lt;table width="739" border="0" cellpadding="2" cellspacing="0"&gt;&#xD;
&lt;tbody&gt;&#xD;
&lt;tr&gt;&#xD;
&lt;td valign="top" width="737"&gt;&#xD;
&lt;p&gt;将事件标记为已处理将会&lt;strong&gt;限制路由事件在事件路由过程中对于侦听器的可见性&lt;/strong&gt;。事件将仍然进行路由过程的其余部分，但&lt;strong&gt;只会在响应中调用在 AddHandler(RoutedEvent, Delegate, Boolean) 方法调用中明确添加的其 HandledEventsToo 为 true 的处理程序&lt;/strong&gt;。 将不会调用实例侦听器上的默认处理程序（比如用可扩展应用程序标记语言 (XAML) 表示的那些处理程序）。处理标记为已处理的事件这种情形并不常见。 &#xD;
&lt;/p&gt;&lt;p&gt;如果您是定义您自己的事件的控件作者，则您在类级别所做的有关事件处理的决策将影响您的控件的用户，以及派生控件的任何用户，并可能会影响您的控件所包含或包含您的控件的其他元素。有关更多信息，请参见 将路由事件标记为&amp;#8220;已处理&amp;#8221;和&amp;#8220;类处理&amp;#8221;。 &#xD;
&lt;/p&gt;&lt;p&gt;在极少数情况下，适合处理其中 Handled 标记为 true 的事件，并通过将 Handled 更改为 false 来修改事件参数。 在控件输入事件的某些区域（比如 KeyDown 与 TextInput 键处理）中，低级别和高级别的输入事件会争用处理，并且每个事件都会尝试使用不同的路由策略，因此，可能必须要这样做。 &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&#xD;
&lt;p&gt;也就是说，在将KeyEventArgs.Handled，我们通过+=来自己注册的处理程序，就无法执行了。一种替代思路就是在不要用+=来注册处理程序，而是调用&lt;strong&gt;AddHandler(RoutedEvent, Delegate, Boolean) &lt;/strong&gt;方法来注册处理程序：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000;"&gt;//之前的处理方式，将监听不到已经处理过的Tab/Enter等键&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000;"&gt;//dataGrid.KeyDown += KeyDownHandler&amp;lt;T&amp;gt;; //注册按键事件&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; &lt;span style="color: #008000;"&gt;//只能通过下列方式来注册&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt; dataGrid.AddHandler(DataGrid.KeyDownEvent, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; KeyEventHandler(KeyDownHandler&amp;lt;T&amp;gt;), &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;但在使用的时候发现，如果当前Cell(TextBlock)处于编辑状态，要按两次Tab/Enter才能跳转到下一列：第一次提交更改，第二次才执行跳转操作。&#xD;
&lt;/p&gt;&lt;p&gt;回过头来看，上面的DataGrid的部分源码，跟进去看了下KeyUp事件的处理，发现KeyUp并没有去更改KeyEventArgs.Handled属性。因此，我们可以考虑在DataGrid上注册自定义KeyUp事件，来做一些额外处理：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; dataGrid.KeyUp += KeyUpHandler&amp;lt;T&amp;gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; KeyUpHandler&amp;lt;T&amp;gt;(&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; sender, KeyEventArgs e) &lt;span style="color: #0000ff;"&gt;where&lt;/span&gt; T : &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;()&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;       DataGrid dataGrid = sender &lt;span style="color: #0000ff;"&gt;as&lt;/span&gt; DataGrid;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;       &lt;span style="color: #0000ff;"&gt;switch&lt;/span&gt; (e.Key)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;       {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;              &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Tab:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt;                     &lt;span style="color: #0000ff;"&gt;goto&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Enter;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;              &lt;span style="color: #0000ff;"&gt;case&lt;/span&gt; Key.Enter:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;                     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (dataGrid.CurrentColumn != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt;                     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;                         &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (dataGrid.IsLastRow() &amp;amp; dataGrid.IsLastCell()) &lt;span style="color: #008000;"&gt;// Last Row And Last Cell (End of the grid)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;                         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;                             dataGrid.AddEntity&amp;lt;T&amp;gt;();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;                         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt;                         &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (dataGrid.IsLastCell()) &lt;span style="color: #008000;"&gt;// Last Cell&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt;                         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  19:&lt;/span&gt;                             dataGrid.SelectedIndex = dataGrid.SelectedIndex + 1;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  20:&lt;/span&gt;                             dataGrid.NextCellToEdit();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  21:&lt;/span&gt;                         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  22:&lt;/span&gt;                         &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; &lt;span style="color: #008000;"&gt;// Normal navigation&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  23:&lt;/span&gt;                         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  24:&lt;/span&gt;                             dataGrid.NextCellToEdit();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  25:&lt;/span&gt;                         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  26:&lt;/span&gt;                     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  27:&lt;/span&gt;                     &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  28:&lt;/span&gt;              &lt;span style="color: #0000ff;"&gt;default&lt;/span&gt;:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  29:&lt;/span&gt;                     &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  30:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101122032369588.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="clip_image001[4]" alt="clip_image001[4]" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101122032386042.png" width="612" border="0" height="526" /&gt;&lt;/a&gt;&#xD;
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2. 最后一行最后一列，Tab/Enter自动增加新行&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;能捕捉到Tab/Enter后，处理就比较简单了；只需判断时候在最后一行、最后一列，如果是，则调用上一篇文章中的增加新行方法：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (dataGrid.IsLastRow() &amp;amp; dataGrid.IsLastCell())&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt;     dataGrid.AddEntity&amp;lt;T&amp;gt;();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3. 增加新行后，自动跳转到新增行的第一列&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;可以尝试在后台代码中，将DataGrid聚焦在新增行的第一列上：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; dataGrid.SelectedItem = entity;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; dataGrid.CurrentColumn = dataGrid.Columns[0];&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; dataGrid.NextCellToEdit();&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;但是在实际使用过程中，可能会遇到如下异常：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101122032427631.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201101/201101122032435830.png" width="458" border="0" height="608" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;这是因为，新增加的行，&lt;strong&gt;可能(有时能成功，有时可能失败)&lt;/strong&gt;还没有来得及在UI显示出来，如果在这时设置SelectedItem/CurrentColumn，并调用ScrollIntoView，就会出现上面的异常。一种代替思路，就是用一个计时器来进行处理，如果执行失败，则下次接着执行，直到成功为止：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; ScrolToFirstColumn(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt; DataGrid dataGrid, &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; entity)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt;     DispatcherTimer timer = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; DispatcherTimer();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt;     timer.Interval = TimeSpan.FromTicks(100);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; sucess = &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;     timer.Tick += (o, e) =&amp;gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!(&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;)sucess)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;             dataGrid.SelectedItem = entity;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;             dataGrid.CurrentColumn = dataGrid.Columns[0];&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt;             dataGrid.NextCellToEdit();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;             sucess = &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;             timer.Stop(); &lt;span style="color: #008000;"&gt;//执行完毕后，就不再执行。&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;     };&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt;     timer.Start();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4. 删除行后，自动选中上一行&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;默认情况下，行被删除行后，DataGrid没有选中任何行。如果想连续删除、或者用Up/Down/Left/Right跳转的话，就需要每次用鼠标点一下，着实不方便。于是提供了此功能：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; DeleteCurrentRow(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt; DataGrid dataGrid)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; entity = dataGrid.SelectedItem;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt;     IList dataSource = dataGrid.ItemsSource &lt;span style="color: #0000ff;"&gt;as&lt;/span&gt; IList;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (entity == &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; || dataSource == &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt; || dataSource.Count == 0)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;     &lt;strong&gt;&lt;font color="#008000"&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; selectedIndex = dataGrid.SelectedIndex; //删除前，记录当前行的位置&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (ExtenderInfo[dataGrid].Deleteable)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;         dataSource.Remove(entity);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;         &lt;strong&gt;&lt;font color="#008000"&gt;dataGrid.SelectedIndex = selectedIndex - 1;//删除后，重置当前行&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;     dataGrid.BeginEdit();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt;     ExtenderInfo[dataGrid].RaiseRowChangedEvent(dataGrid,&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; EntityChangedEventArgs() { ChangedEntities = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; List&amp;lt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&amp;gt; { entity }, Type = &lt;span style="color: #006080;"&gt;"Delete"&lt;/span&gt; });&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  19:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;5. Up/Down/Left/Right自动编辑&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;上一篇文章中，通过在DataGrid的KeyDown事件中，见按键记录到DataGrid.Tag中，然后进入编辑状态时再赋值给单元格中的文本框(TextBox)，来实现即时编辑功能。但在使用的时候，发现如果使用中文输入法、或者列使用的是自定义模板列(不是TextBox)，就会遇到问题：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果是中文输入法+默认的TextBox：DataGrid会将第一个字符赋给TextBox，这样就多出一个字符，每次得多按一次BackSpace键。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果是使用自定义模板列，而不是TextBox，就会丢失第一次字符按键。&lt;/p&gt;&#xD;
&lt;p&gt;一种替代的思路，就是在捕捉Up/Down/Left/Right后，让DataGrid立即进入编辑状态。如上面第1点所述，还是要在KeyUp事件中进行处理。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;6. 不给代码怎马叫給力&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://files.cnblogs.com/happyhippy/happyhippy.cnblogs.BatchInput.rar" target="_blank"&gt;happyhippy.cnblogs.com.BatchInput.rar&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/happyhippy/aggbug/1934006.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/happyhippy/archive/2011/01/12/1934006.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/happyhippy/archive/2010/12/26/1917383.html</id><title type="text">[SilverLight] DataGrid实现批量输入(like Excel)</title><summary type="text">DataGrid 控件提供了一种灵活的方式来以行和列的形式显示数据集合。但却没有提供增加、删除行、即时输入等功能，若要实现类似于Winform下的DataGrid批量录入功能，还得做一些手脚：    1. 显示行号；    2. 即时输入；    3. 增加新行；    4. 删除行；    5. 复制、粘贴行/多行。    本文针对这几个问题，提出一些解决思路。</summary><published>2010-12-26T13:40:00Z</published><updated>2010-12-26T13:40:00Z</updated><author><name>Silent Void</name><uri>http://www.cnblogs.com/happyhippy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/happyhippy/archive/2010/12/26/1917383.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/happyhippy/archive/2010/12/26/1917383.html"/><content type="html">&lt;p&gt;DataGrid 控件提供了一种灵活的方式来以行和列的形式&lt;strong&gt;显示数据集合&lt;/strong&gt;。但却没有提供增加、删除行、即时输入等功能，若要实现类似于Winform下的DataGrid批量录入功能，还得做一些手脚：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1. 显示行号；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2. 即时输入；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3. 增加新行；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4. 删除行；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5. 复制、粘贴行/多行。&lt;/p&gt; &lt;p&gt;本文针对这几个问题，提出一些解决思路。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;1. 显示行号&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;网上也有一些显示行号的文章，但都是一个处理思路，就是在LoadingRow事件中做手脚，如这篇文章中所提供的思路《&lt;a href="http://www.cnblogs.com/024hi/archive/2009/12/17/1626490.html"&gt;[Silverlight]奇技银巧系列-4 在DataGrid中显示行号&lt;/a&gt;》：&lt;/p&gt; &lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt; &lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; dataGrid1.LoadingRow += &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; EventHandler&amp;lt;DataGridRowEventArgs&amp;gt;(dataGrid1_LoadingRow);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; dataGrid1_LoadingRow(&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; sender, DataGridRowEventArgs e) {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; index = e.Row.GetIndex();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;     var cell = dataGrid1.Columns[0].GetCellContent(e.Row) &lt;span style="color: #0000ff;"&gt;as&lt;/span&gt; TextBlock;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;     cell.Text = (index + 1).ToString();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;SL帮助文档中对LoadingRow的解释是：&amp;#8220;若要改进性能，DataGrid 控件不针对绑定数据源中的每个数据项实例化 DataGridRow 对象。而是&lt;strong&gt;仅当需要时才由数据网格创建 DataGridRow 对象，并尽量重复使用这些对象&lt;/strong&gt;。例如，数据网格为当前位于视图中的每个数据项创建一个 DataGridRow 对象，并&lt;strong&gt;在行滚出视图之外时回收它&lt;/strong&gt;。&amp;#8221;&lt;/p&gt;&#xD;
&lt;p&gt;这个处理思路的一个问题，就是当DataGrid的行比较多，超出可视区域(出现滚动条)后；然后再删除前面的行，行号就废了。因为处于可视区域中的现有&lt;strong&gt;没有被删除的行，不会执行LoadingRow事件&lt;/strong&gt;，所以显示的Index不会被更新。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;处理思路&lt;/strong&gt;：&amp;nbsp;&amp;nbsp; &lt;/p&gt;&#xD;
&lt;p&gt;我们一般是将ObservableCollection&amp;lt;Entity&amp;gt;作为DataGrid的数据源。一个变态的处理思路，就是给Entity增加一个Index属性(修改时引发PropertyChanged事件)，然后再DataGrid的LoadingRow/UnloadingRow中，取得DataGrid的数据源ObservableCollection&amp;lt;Entity&amp;gt;，然后更新每个Index的值，囧。。。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 不过这样也有一个问题，就是在排序后，Index不会重新计算，显得有点乱。不知道排序会引发啥事件，如果在排序事件中也来更新一次Index，就没有问题了。哪位知道排序会引发啥事件，请告诉我，谢谢。/:)&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;2. 即时输入&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;默认情况下，DataGrid的Cell(TextBlock)不是出于编辑状态，要按F2或者鼠标单击，才能进入编辑状态(TextBox)。如果用鼠标点，或者每次都按F2，用起来非常不爽。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;处理思路：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;参考文章《&lt;a href="http://www.codeproject.com/KB/silverlight/SilverLikeExcel.aspx" target="_blank"&gt;An attempt to make the Silverlight DataGrid similar to Excel&lt;/a&gt;》，里面提出的思路就是在KeyDown\GotFocus\CellEditEnded三个事件中进行处理：&lt;br /&gt;(1) KeyDown事件中，捕捉按键，如果是字符键，则记录到DataGrid.Tag中，然后执行dataGrid.BeginEdit()，强制DataGrid进入编辑状态。&lt;br /&gt;(2) GotFocus事件中，将DataGrid.Tag中记录的字符取出来，然后付给输入框(TextBox);&lt;br /&gt;(3) CellEditEnded事件中，清理DataGrid.Tag。&lt;/p&gt;&#xD;
&lt;p&gt;在该文的回复中，有人提出了一个可替代的事件组合：TextInput/&lt;code&gt;PreparingCellForEdit&lt;/code&gt;/KeyDown。也是一个处理思路。&lt;/p&gt;&#xD;
&lt;p&gt;天杀的M$，为啥让DataGrid可编辑，却不能即时输入呢。要用这种变态的方式去处理。。。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3. 增加新行&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;貌似新版本的SL，可以支持增加新行了。《&lt;a href="http://www.cnblogs.com/jv9/archive/2010/09/03/1817650.html"&gt;微软发布Silverlight 4新版并更新Silverlight Tools和SDK&lt;/a&gt;》，但问题是，找遍了网络，竟然没有一个例子，M$的论坛上，也是只有提问没有答案。。。所以还是得自己动手。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;处理思路：&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;快捷键：DataGrid的KeyDown事件中，判断按键；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 增加新行：增加新行比较简单，上面提到，DataGrid的数据源是ObservableCollection&amp;lt;Entity&amp;gt;，因此，只要我们向该&lt;strong&gt;集合中增加一个元素&lt;/strong&gt;，就能达到增加新行的目的。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4. 删除行&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;处理思路同增加新行：&lt;/p&gt;&#xD;
&lt;p&gt;快捷键：KeyDown中判断按键；&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 删除行：取得DataGrid的当前选择行dataGrid.SelectedItem as Entity，然后从将Entity从ObservableCollection&amp;lt;Entity&amp;gt;中删除。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;5. 复制/粘行&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;处理思路1：&lt;br /&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp; 《&lt;a href="http://www.codeproject.com/KB/silverlight/SilverLikeExcel.aspx" target="_blank"&gt;An attempt to make the Silverlight DataGrid similar to Excel&lt;/a&gt;》一文中，也提供了一个复制/粘贴的思路：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201012/201012262139507710.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201012/201012262139523858.png" border="0" width="787" height="204" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;主要分三个步骤：&lt;br /&gt;(1). 获取DataGrid选择行，然后将每个cell（TextBlock）的中的文本数据，用&amp;#8220;\t&amp;#8221;分割，得到文本值；(如果Cell不在可视区域内，则调用dataGrid.ScrollIntoView，让Cell显示出来，然后才能取到TextBlock/TextBox)&lt;br /&gt;(2). 将数据保存到系统的粘贴板:&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; var clipboardData = (ScriptObject)HtmlPage.Window.GetProperty(&lt;span style="color: #006080;"&gt;"clipboardData"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; clipboardData.Invoke(&lt;span style="color: #006080;"&gt;"setData"&lt;/span&gt;, &lt;span style="color: #006080;"&gt;"text"&lt;/span&gt;, &lt;span style="color: #006080;"&gt;"格式化的自定义格式的数据"&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;(3). 从粘贴板上将数据取回来，再赋值给目标行中的Cell(TextBox):&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; var clipboardData = (ScriptObject)HtmlPage.Window.GetProperty(&lt;span style="color: #006080;"&gt;"clipboardData"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; textData = clipboardData.Invoke(&lt;span style="color: #006080;"&gt;"getData"&lt;/span&gt;, &lt;span style="color: #006080;"&gt;"text"&lt;/span&gt;).ToString();&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;但该文章中，只提供了&lt;strong&gt;单行复制/粘贴&lt;/strong&gt;的功能；而且这段代码有很大局限性，&lt;strong&gt;只能在IE中运行&lt;/strong&gt;。&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;处理思路2：&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上面的复制/粘贴功能，只局限在IE中运行。另一个处理思路，可以做两点改进：&lt;/p&gt;&#xD;
&lt;p&gt;(1)&amp;nbsp; 上面提到，DataGrid的数据源是ObservableCollection&amp;lt;T&amp;gt;，只要改变该集合中的值，SL就会自动刷新DataGrid。因此我们可以不用去操作DataGrid中的Cell，而是直接操作ObservableCollection&amp;lt;T&amp;gt;。拷贝的时候，对选中的一个或多个元素(Entity)执行xml序列化得到文本值；粘贴的时候，将文本值反序列化回来，然后对掉选中的元素(Entity)逐个属性赋值。&lt;/p&gt;&#xD;
&lt;p&gt;从ObservableCollection&amp;lt;T&amp;gt;得到文本值由两个处理思路：可以按上面描述的序列化来处理；也可以按处理思路1种的文本拼接思路，按照csv格式来进行拼接：属性值之间以&amp;#8220;\t&amp;#8221;分隔，元素(Entity)之间以&amp;#8220;\r\n&amp;#8221;分隔。&lt;/p&gt;&#xD;
&lt;p&gt;按csv格式拼接的好处，就是拷贝的数据，可以直接粘贴到Excel中。而序列化的好处，就是可以保证兼容性；譬如批量录入过程耗时可能比较长，中途可能需要跳转到其他页面、或者离开很久、或者下班关机，那前面录入的相当于白干了；因此需要在客户端提供了一个临时保存的功能：把当前数据保存到文件(SL4支持将数据保存独立存储区中)，下次再从文件中把数据加载出来；但如果中途系统升级了，增加或者减少了一个字段/列，则序列化可以忽略增加/减少的列，继续正常工作。但CSV格式拼接出来的文本，缺少列描述信息，就挂了。。。&lt;/p&gt;&#xD;
&lt;p&gt;(2) 用一个TextBox做中转。将文本值赋值给中转的TextBox，然后对TextBox按Ctrl+C，从而将数据拷贝到系统的粘贴板；粘贴的过程正好反过来，先将系统粘贴板的数据，粘贴到中转用的TextBox，然后再取得TextBox中的值。&lt;/p&gt;&#xD;
&lt;p&gt;整个处理过程如下图所示：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201012/201012262139546659.png" border="0" width="803" height="280" /&gt; &lt;/p&gt;&#xD;
&lt;p&gt;在复制/粘贴的过程中，可能还会遇到一种情况，即选择了DataGrid中的N行，然后复制；但粘贴的时候，可能会选择M行，有三种情况需要考虑：&lt;br /&gt;(1) M=N：这种情况下，正好元素可以一一匹配上；逐个元素按属性赋值就行；&lt;br /&gt;(2) M&amp;gt;N：虽然粘贴时，选择的行数更多，但我们可以忽略多出的行(M-N)，只处理前面的N行；&lt;br /&gt;(3) M&amp;lt;N：此时，需要考虑多出的复制行(N-M)要怎么处理了；有三种处理办法：(1) 忽略多出的复制行；(2) 按照Excel的处理思路，只允许粘贴到连续的N行中；(3) 我的处理思路是，可以跨行粘贴，对于多出的行，可以插入到ObservableCollection&amp;lt;T&amp;gt;中。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;6. 类图结构&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201012/201012262140008606.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="ClassDiagram1" alt="ClassDiagram1" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201012/201012262140039671.png" border="0" width="759" height="819" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;7. 使用方法&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; dataGrid.UseExtender&amp;lt;Employee&amp;gt;();&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;这是最简单的情况，只提供基本的即时输入、增加、删除、复制、粘贴功能等；一个稍微复杂点的调用方式如下：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000;"&gt;//happyhippy.cnblogs.com&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000;"&gt;//方法定义原型&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; UseExtender&amp;lt;T&amp;gt;(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt; DataGrid dataGrid, &lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; autoIncreaseField = &lt;span style="color: #006080;"&gt;""&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; useXmlCopy = &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;, Action&amp;lt;DataGrid, EntityChangedEventArgs&amp;gt; rowsChanged = &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;,&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; addable = &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; deleteable = &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;where&lt;/span&gt; T : &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;()&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt; &lt;span style="color: #008000;"&gt;//调用：&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt; dataGrid.UseExtender&amp;lt;Employee&amp;gt;(&lt;span style="color: #006080;"&gt;"Index"&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;, &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;                 (s, eventArg) =&amp;gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt;                     &lt;span style="color: #008000;"&gt;//取得刚操作(插入/删除)的元素集合，可以干一些后续的事情。。。&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;                     IList&amp;lt;Employee&amp;gt; changedEntities = eventArg.ChangedEntities &lt;span style="color: #0000ff;"&gt;as&lt;/span&gt; IList&amp;lt;Employee&amp;gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;                 }, &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;, &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;运行效果：&lt;br /&gt;&amp;nbsp;&lt;a href="http://images.cnblogs.com/cnblogs_com/happyhippy/201012/201012262140056998.png"&gt;&lt;img style="border: 0px none ; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/happyhippy/201012/201012262140067389.png" border="0" width="572" height="382" /&gt;&lt;/a&gt;  &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;8. 上代码&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://files.cnblogs.com/happyhippy/happyhippy.cnblogs.BatchInput.rar" target="_blank"&gt;DataGridLikeExcel.rar&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/happyhippy/aggbug/1917383.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/happyhippy/archive/2010/12/26/1917383.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/happyhippy/archive/2010/11/07/1871258.html</id><title type="text">SpeechSynthesizer/WaveHeader 存在严重的内存泄漏</title><summary type="text">    .Net Framework 3.0带了个System.Speech.dll，装个语音包，然后就可以实现文字朗读等功能。最近在使用的时候，发现随着程序的运行，程序占用的内存一直在增长，直到程序崩溃。     用WinDbg抓了个Dump，然后看了下，里面一堆没有释放的SPVTEXTFRAG、AudioDeviceOut+InItem、WAVEHDR、WaveHeader对象。。。</summary><published>2010-11-07T12:52:00Z</published><updated>2010-11-07T12:52:00Z</updated><author><name>Silent Void</name><uri>http://www.cnblogs.com/happyhippy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/happyhippy/archive/2010/11/07/1871258.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/happyhippy/archive/2010/11/07/1871258.html"/><content type="html">&lt;p&gt;.Net Framework 3.0带了个System.Speech.dll，装个语音包，然后就可以实现文字朗读等功能。最近在使用的时候，发现随着程序的运行，程序占用的内存一直在增长，直到程序崩溃。&lt;/p&gt; &lt;p&gt;用WinDbg抓了个Dump，然后看了下，里面一堆没有释放的SPVTEXTFRAG、AudioDeviceOut+InItem、WAVEHDR、WaveHeader对象，于是写了一小段来测试：&lt;/p&gt; &lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt; &lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000;"&gt;//happyhippy.cnblogs.com&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; System.Speech.Synthesis;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;using&lt;/span&gt; (SpeechSynthesizer ss = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; SpeechSynthesizer())&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;.MaxValue; i++)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;         ss.Speak(i.ToString());&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;跑了几个小时，然后抓了个内存，开始干活：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;1. 看下内存中有哪些对象&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; 0:000&amp;gt; .load clr20/sos.dll&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; 0:000&amp;gt; !dumpheap -stat&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; PDB symbol &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; mscorwks.dll not loaded&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt; total 275193 objects&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt; Statistics:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;       MT    Count    TotalSize Class Name&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt; 70441ff8        1           12 System.RuntimeTypeHandle&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt; 7043fc7c        1           12 System.__Filters&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt; &lt;span style="color: #008000;"&gt;//。。。。。。。。。。。。中间省略了一堆。。。。。。。。。。。&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt; 704431a8       18         1008 System.Collections.Hashtable&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt; 7042c938       65         1560 System.Security.Policy.StrongNameMembershipCondition&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt; 70441cd4       81         1620 System.RuntimeType&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt; 70441784       16         1820 System.Char[]&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt; 7042c6e4      232         6496 System.Security.SecurityElement&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt; 70442b84      278         6672 System.Collections.ArrayList&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt; 704435c4       17        75056 System.Byte[]&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt; 5610529c     4297        85940 System.Speech.Internal.AlphabetConverter+PhoneMapData+ConversionUnit&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt; 704432a4       18       181896 System.Collections.Hashtable+bucket[]&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  19:&lt;/span&gt; 70414324      376       319064 System.Object[]&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  20:&lt;/span&gt; 70440b54    13185       396696 System.String&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  21:&lt;/span&gt; 5610ab38     7538       693496 System.Speech.Synthesis.TtsEngine.SPVTEXTFRAG&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  22:&lt;/span&gt; 56105c50    63264      1012224 System.Speech.Internal.Synthesis.AudioDeviceOut+InItem&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  23:&lt;/span&gt; 560f2694    65652      2626080 System.Speech.Internal.Synthesis.WAVEHDR&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  24:&lt;/span&gt; &lt;strong&gt;&lt;font size="4"&gt;56105b6c&lt;/font&gt;&lt;/strong&gt;    63264      3289728 System.Speech.Internal.Synthesis.&lt;font size="4"&gt;WaveHeader&lt;/font&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  25:&lt;/span&gt; &lt;strong&gt;&lt;font color="#ff0000"&gt;002be948    56465    172964660      Free&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  26:&lt;/span&gt; Total 275193 objects&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  27:&lt;/span&gt; Fragmented blocks larger than 0.5 MB:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  28:&lt;/span&gt;     Addr     Size      Followed by&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  29:&lt;/span&gt; 1228c6d8    0.5MB         12311d7c System.Speech.Synthesis.TtsEngine.SPVTEXTFRAG&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  30:&lt;/span&gt; 123293e0    0.6MB         123baa64 System.Speech.Synthesis.TtsEngine.SPVTEXTFRAG&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  31:&lt;/span&gt; 124be36c    1.9MB         1269d898 System.Speech.Synthesis.TtsEngine.SPVTEXTFRAG&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  32:&lt;/span&gt; 126a39f0    1.3MB         127e6644 System.Speech.Synthesis.TtsEngine.SPVTEXTFRAG&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;列表中的第25行，172M的Free状态的内存。&lt;/p&gt;&#xD;
&lt;p&gt;最后4行(29~32)的内存碎片，用DumpObj看了下，都是Free状态。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;2. 看看终结队列中有哪些对象&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; 0:000&amp;gt; !FinalizeQueue -detail&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; SyncBlocks to be cleaned up: 0&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; MTA Interfaces to be released: 0&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt; STA Interfaces to be released: 0&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt; ----------------------------------&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt; generation 0 has 2973 finalizable objects (068fdec4-&amp;gt;06900d38)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt; generation 1 has 11 finalizable objects (068fde98-&amp;gt;068fdec4)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt; generation 2 has 60304 finalizable objects (068c3058-&amp;gt;068fde98)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt; Ready &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt; finalization 0 objects (06900d38-&amp;gt;06900d38)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt; Statistics:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;       MT    Count    TotalSize Class Name&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt; 7043a304        1           16 System.WeakReference&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt; 7002d1c8        1           20 System.ComponentModel.AsyncOperation&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt; 5610a9c0        1           20 System.Speech.Synthesis.SpeechSynthesizer&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt; 5610576c        1           20 System.Speech.Internal.ObjectTokens.RegistryDataKey&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt; 5610581c        1           24 System.Speech.Internal.ObjectTokens.ObjectToken&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt; 56105ae8        1           56 System.Speech.Internal.Synthesis.AudioDeviceOut&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt; 70427b90        4           80 Microsoft.Win32.SafeHandles.SafeWaitHandle&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  19:&lt;/span&gt; 561092e0        1          176 System.Speech.Internal.Synthesis.VoiceSynthesis&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  20:&lt;/span&gt; 7043b370        9          180 Microsoft.Win32.SafeHandles.SafeRegistryHandle&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  21:&lt;/span&gt; 70441128        4          224 System.Threading.Thread&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  22:&lt;/span&gt; &lt;strong&gt;&lt;font color="#ff0000"&gt;56105b6c&lt;/font&gt;&lt;/strong&gt;    63264      3289728 System.Speech.Internal.Synthesis.WaveHeader&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  23:&lt;/span&gt; Total 63288 objects&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;我靠，内存中3289728个WaveHeader全部挂在终结队列中。一个可能的原因就是：&lt;strong&gt;WaveHeader对象中实现了析构函数&lt;/strong&gt;，&lt;strong&gt;并且程序使用完WaveHeader对象后，没有手动释放(Dispose)，而是等着GC来自动回收。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;3. 用Reflector看WaveHeader的源代码&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;sealed&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; WaveHeader : IDisposable&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;// Fields&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; _dwBufferLength;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; GCHandle _gcHandle = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; GCHandle();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; GCHandle _gcHandleWaveHdr = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; GCHandle();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; WAVEHDR _waveHdr = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; WAVEHDR();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; WAVE_FORMAT_PCM = 1;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; WHDR_BEGINLOOP = 4;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; WHDR_DONE = 1;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; WHDR_ENDLOOP = 8;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; WHDR_INQUEUE = 0x10;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; WHDR_PREPARED = 2;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;// Methods&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; WaveHeader(&lt;span style="color: #0000ff;"&gt;byte&lt;/span&gt;[] buffer)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._dwBufferLength = buffer.Length;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  19:&lt;/span&gt;         &lt;strong&gt;&lt;font color="#ff0000"&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);//申请内存&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  20:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  21:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  22:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Dispose()&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  23:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  24:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.Dispose(&lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  25:&lt;/span&gt;         GC.SuppressFinalize(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  26:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  27:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  28:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Dispose(&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; disposing)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  29:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  30:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (disposing)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  31:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  32:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.ReleaseData();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  33:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._gcHandleWaveHdr.IsAllocated)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  34:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  35:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._gcHandleWaveHdr.Free();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  36:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  37:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  38:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  39:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  40:&lt;/span&gt;     ~WaveHeader()&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  41:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  42:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;.Dispose(&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  43:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  44:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  45:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; ReleaseData()&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  46:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  47:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._gcHandle.IsAllocated)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  48:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  49:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._gcHandle.Free();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  50:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  51:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  52:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  53:&lt;/span&gt;     &lt;span style="color: #008000;"&gt;// Properties&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  54:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; SizeHDR&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  55:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  56:&lt;/span&gt;         get&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  57:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  58:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; Marshal.SizeOf(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._waveHdr);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  59:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  60:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  61:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  62:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; GCHandle WAVEHDR&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  63:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  64:&lt;/span&gt;         get&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  65:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  66:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._gcHandleWaveHdr.IsAllocated)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  67:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  68:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._waveHdr.lpData = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._gcHandle.AddrOfPinnedObject();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  69:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._waveHdr.dwBufferLength = (&lt;span style="color: #0000ff;"&gt;uint&lt;/span&gt;) &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._dwBufferLength;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  70:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._waveHdr.dwBytesRecorded = 0;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  71:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._waveHdr.dwUser = 0;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  72:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._waveHdr.dwFlags = 0;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  73:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._waveHdr.dwLoops = 0;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  74:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._waveHdr.lpNext = IntPtr.Zero;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  75:&lt;/span&gt;                 &lt;strong&gt;&lt;font color="#ff0000"&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._gcHandleWaveHdr = GCHandle.Alloc(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._waveHdr, GCHandleType.Pinned);//申请内存&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  76:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  77:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._gcHandleWaveHdr;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  78:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  79:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  80:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;如我们所料，的确定义了一个析构函数（~&lt;strong&gt;WaveHeader&lt;/strong&gt;()），WaveHealder实现了Dispose模式。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;4.&amp;nbsp; 进一步分析，看看WaveHeader都申请了啥资源，为啥要实现Dispose模式&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;WaveHeader的构造函数中，申请了一片Pinned状态的内存&lt;strong&gt;this._gcHandle = GCHandle.Alloc(&lt;/strong&gt;&lt;a&gt;&lt;strong&gt;buffer&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;, GCHandleType.Pinned)，&lt;/strong&gt;并且其WAVEHDR属性的实现中，也通过延迟加载的方式申请了一片Pinned状态的内存&lt;strong&gt;this._gcHandleWaveHdr = GCHandle.Alloc(this._waveHdr, GCHandleType.Pinned)。&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/strong&gt;MSDN对GCHander的阐述如下：(FROM &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.runtime.interopservices.gchandle.aspx" target="_blank"&gt;MSDN&lt;/a&gt;)&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;GCHandle 类与 GCHandleType 枚举结合使用以创建对应于任何托管对象的句柄。此句柄可为以下四种类型之一：Weak、WeakTrackResurrection、Normal 或 Pinned。分配了句柄以后，在非托管客户端保留唯一的引用时，可以使用它防止垃圾回收器回收托管对象。如果没有这样的句柄，则在该对象代表非托管客户端完成工作以前，有可能被垃圾回收器回收。 &lt;br /&gt;&lt;br /&gt;用 GCHandle 创建一个固定对象，该对象返回��个内存地址，并防止垃圾回收器在内存中移动该对象。 &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#ff0000" size="4"&gt;超出范围时，您必须通过调用Free方法显式释放它；否则，可能会发生内存泄漏。&lt;/font&gt;&lt;/strong&gt;当您释放固定的句柄时，如果没有对关联对象的其他引用，则关联对象将解除固定，并可以被当成垃圾回收。&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&#xD;
&lt;p&gt;也就是说，通过GCHandler.Alloc申请的内存，必须通过调用GCHandler.Free方法来手动释放。表面上看来，WaveHeader的实现中，的确有手动释放这些申请的内存。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;5.&amp;nbsp; WaveHeader在哪儿使用&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;SpeechSynthesizer封装了一对东西，有点儿绕，我顺着Speak方法找了N久，没有找到使用WaveHeader的地方。&lt;/p&gt;&#xD;
&lt;p&gt;只好换另一个思路：在上面的第1步中，我们可以看到，WaveHeader的MT Address为56105b6c，于是：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;0:000&amp;gt; !dumpheap -MT 56105b6c&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #008000;"&gt;//。。。省却6万多行。。。  &lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;127fabdc 56105b6c       52     &lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;12800a64 56105b6c       52     //找到一个还活着的对象&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;total 63264 objects&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;Statistics:&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;MT    Count    TotalSize Class Name&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;56105b6c    63264      3289728 System.Speech.Internal.Synthesis.WaveHeader&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;Total 63264 objects&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;然后找到一个还活着的对象(地址为12800a64)，看看它被谁引用了：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;0:000&amp;gt; !gcroot 12800a64&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;Note: Roots found on stacks may be &lt;span style="color: #0000ff;"&gt;false&lt;/span&gt; positives. Run &lt;span style="color: #006080;"&gt;"!help gcroot"&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;for&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;more info.&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;Scan Thread 0 OSTHread 3668&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;ESP:1df238:Root:01f67e1c(System.Speech.Internal.Synthesis.VoiceSynthesis)-&amp;gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;01f6841c(System.Speech.Internal.Synthesis.AudioDeviceOut)-&amp;gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;01f68570(System.Collections.Generic.List`1[[System.Speech.Internal.Synthesis.AudioDeviceOut+InItem, System.Speech]])-&amp;gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;02f91c10(System.Object[])-&amp;gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;020e4088(System.Speech.Internal.Synthesis.AudioDeviceOut+InItem)-&amp;gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;12800a64(System.Speech.Internal.Synthesis.WaveHeader)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;Scan Thread 2 OSTHread 2c5c&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;Scan Thread 3 OSTHread 1160&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;Scan Thread 4 OSTHread 211c&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;Scan Thread 6 OSTHread 22d4&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;Scan Thread 7 OSTHread 2fcc&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;Scan Thread 8 OSTHread 377c&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&amp;nbsp;&amp;nbsp; 这里，我们终于可以看到路径了：&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;SpeechSynthesizer&lt;br /&gt;-&amp;gt;VoiceSynthesis&lt;br /&gt;-&amp;gt;AudioDeviceOut&lt;br /&gt;-&amp;gt; List&amp;lt;AudioDeviceOut + InItem&amp;gt; &lt;br /&gt;-&amp;gt; AudioDeviceOut + InItem（内部类）&lt;br /&gt;-&amp;gt; WaveHeader&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 终于找到目标了：AudioDeviceOut。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;6.&amp;nbsp; 怎么使用WaveHeader&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;AudioDeviceOut的代码页有点长，这里只截出部分使用WaveHeader的代码：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; Play(&lt;span style="color: #0000ff;"&gt;byte&lt;/span&gt;[] buffer)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._deviceOpen)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; length = buffer.Length;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._bytesWritten += length;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;         WaveHeader waveHeader = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; WaveHeader(buffer);&lt;strong&gt;&lt;font color="#ff0000"&gt;//上面第3节提到，这里通过GCHandler.Alloc申请了内存&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;         GCHandle wAVEHDR = waveHeader.WAVEHDR;&lt;strong&gt;&lt;font color="#ff0000"&gt;//上面第3节提到，这里通过GCHandler.Alloc申请了内存&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt;         MMSYSERR errorCode = SafeNativeMethods.waveOutPrepareHeader(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._hwo, wAVEHDR.AddrOfPinnedObject(), waveHeader.SizeHDR);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (errorCode != MMSYSERR.NOERROR)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; AudioException(errorCode);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;lock&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._noWriteOutLock)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (!&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;._aborted)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;lock&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  19:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  20:&lt;/span&gt;                     InItem item = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; InItem(waveHeader);&lt;strong&gt;&lt;font color="#ff0000"&gt;//InItem封装了一下WaveHeader，也没啥&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  21:&lt;/span&gt;                     &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn.Add(item); &lt;font color="#ff0000"&gt;&lt;strong&gt;//将Item加入到List中&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  22:&lt;/span&gt;                     &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._evt.Reset();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  23:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  24:&lt;/span&gt;                 errorCode = SafeNativeMethods.waveOutWrite(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._hwo, wAVEHDR.AddrOfPinnedObject(), waveHeader.SizeHDR);&lt;font color="#ff0000"&gt;&lt;strong&gt;//P/Invoke向设备输出数据&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  25:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (errorCode != MMSYSERR.NOERROR)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  26:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  27:&lt;/span&gt;                     &lt;span style="color: #0000ff;"&gt;lock&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  28:&lt;/span&gt;                     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  29:&lt;/span&gt;                         &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn.RemoveAt(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn.Count - 1);&lt;strong&gt;&lt;font color="#ff0000"&gt;//如果出错了，从List删除一个Item&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  30:&lt;/span&gt;                         &lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; AudioException(errorCode);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  31:&lt;/span&gt;                     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  32:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  33:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  34:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  35:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  36:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;在这里，Play方法了面，终于实例化了WaveHeader和WaveHDR(GCHandler)；但是实例化的WaveHeader又被InItem封装了一下，加入到List&amp;lt;InItem&amp;gt; _queueIn中。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Play&lt;strong&gt;方法里面创建了WaveHeader，但是却没有看到释放WaveHeader的代码&lt;/strong&gt;。&lt;/p&gt;&#xD;
&lt;p&gt;那我们再来看下，其他地方有没有释放WaveHeader的代码：既然InItem/WaveHeader被加入到_queueIn中了，程序应该还要使用WaveHeader；那么当InItem从该_queueIn中移出的时候，应该就会释放WaveHeader了吧。顺着这个思路继续往下看。。。&lt;/p&gt;&#xD;
&lt;p&gt;很不幸，就在Play方法里面：当判断播放出错的时候，会把InItem从_queueIn中移出(上面第29行)，但是却&lt;font color="#ff0000"&gt;&lt;strong&gt;没有释放InItem/WaveHeader&lt;/strong&gt;&lt;/font&gt;。&lt;/p&gt;&#xD;
&lt;p&gt;另一个将InItem从_queueIn中移出的地方是CallBackProc，AudioDeviceOut在构造函数中初始化了一个委托：this._delegate = new SafeNativeMethods.WaveOutProc(this.CallBackProc); 从字面上理解，应该是输出声音完毕后，调用这个回调函数，来释放内存：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; CallBackProc(IntPtr hwo, MM_MSG uMsg, IntPtr dwInstance, IntPtr dwParam1, IntPtr dwParam2)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (uMsg == MM_MSG.MM_WOM_DONE)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;lock&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;             InItem item = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn[0];&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;             item.ReleaseData();&lt;strong&gt;&lt;font color="#ff0000"&gt;//释放InItem/WaveHeader&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn.RemoveAt(0); &lt;strong&gt;&lt;font color="#ff0000"&gt;//移除InItem&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueOut.Add(item);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;while&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn.Count &amp;gt; 0)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt;             {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;                 item = &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn[0];&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (item._waveHeader != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;                     &lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; ((&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._asyncDispatch != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;) &amp;amp;&amp;amp; !&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;._aborted)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  19:&lt;/span&gt;                 {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  20:&lt;/span&gt;                     &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._asyncDispatch.Post(item._userData);&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  21:&lt;/span&gt;                 }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  22:&lt;/span&gt;                 &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn.RemoveAt(0);&lt;strong&gt;&lt;font color="#ff0000"&gt;//移除InItem，但是却没有释放InItem/WaveHeader&lt;/font&gt;&lt;/strong&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  23:&lt;/span&gt;             }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  24:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  25:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._queueIn.Count == 0)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  26:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  27:&lt;/span&gt;             &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._evt.Set();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  28:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  29:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  30:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;代码中，可以看到，当uMsg == MM_MSG.MM_WOM_DONE，才会执行释放操作。MM_MSG枚举有三个可选值：MM_WOM_CLOSE = 0x3bc, MM_WOM_DONE = 0x3bd, MM_WOM_OPEN = 0x3bb，暂时不太清楚是回调函数的uMsg参数 否可能会传入其他值；如果传入了其他值，显然&lt;font color="#ff0000"&gt;&lt;strong&gt;InItem/WaveHeader有没有被释放。&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;即使uMsg == MM_MSG.MM_WOM_DONE，我们来看下释放的代码，上面第8~9行，从_queueIn中移除InItem/WaveHeader的时候，的确执行了ReleaseData()来释放内存，但是看该方法的源代码：&lt;/p&gt;&#xD;
&lt;div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: consolas,'Courier New',courier,monospace; max-height: 200px; font-size: 8pt; cursor: text;"&gt;&#xD;
&lt;div style="border-style: none; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000;"&gt;//happyhippy.cnblogs.com&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000;"&gt;//InItem&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; ReleaseData()&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   4:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._waveHeader != &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   6:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   7:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._waveHeader.ReleaseData();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   8:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;   9:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  10:&lt;/span&gt; &lt;span style="color: #008000;"&gt;//WaveHeader&lt;/span&gt;&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  11:&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;internal&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; ReleaseData()&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  12:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._gcHandle.IsAllocated)&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  14:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  15:&lt;/span&gt;         &lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;._gcHandle.Free();&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  16:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: white; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  17:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: consolas,'Courier New',courier,monospace; color: black; font-size: 8pt;"&gt;&lt;span style="color: #606060;"&gt;  18:&lt;/span&gt;  &lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;里面调用WaveHeader.ReleaseData()来释放内存，不是调用Dispose来释放内存。上面提到，Play方法中，第8行GCHandle wAVEHDR = waveHeader.WAVEHDR申请了内存，&lt;strong&gt;&lt;font color="#ff0000"&gt;但是ReleaseData()方法并没有释放该内存。应该调用Dispose来释放内存，而不是调用ReleaseData()。&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;然后在回过头来看CallBackProc方法，从源代码中可以看到，其&lt;strong&gt;&lt;font color="#ff0000"&gt;只释放了_queueIn中第一个InItem/WaveHeader，后续的InItem/WaveHeader从_queueIn中移除的时候，并没有释放内存&lt;/font&gt;&lt;/strong&gt;。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;&amp;nbsp; GCHandler.Alloc申请的内存，必须通过调用Free方法显式释放它；否则，可能会发生内存泄漏。&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;&lt;/font&gt;&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;7.&amp;nbsp; 解决办法&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;无解。&lt;/p&gt;&#xD;
&lt;p&gt;那封装的一大坨，都是Internal。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/happyhippy/aggbug/1871258.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/happyhippy/archive/2010/11/07/1871258.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
