<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_bengxia-未来与荣耀</title><subtitle type="text">Bad artists copy, Good artists steal -- Picasso</subtitle><id>http://feed.cnblogs.com/blog/u/17532/rss</id><updated>2011-12-30T07:54:32Z</updated><author><name>bengxia</name><uri>http://www.cnblogs.com/bengxia/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bengxia/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/17532/rss"/><entry><id>http://www.cnblogs.com/bengxia/archive/2011/12/30/2307588.html</id><title type="text">MY 2012 GOALS</title><summary type="text">1. 每月读1本书；2. 每天背20个单词；3. 每周锻炼身体3次；4. 每天练习口语40分钟；5.每月写5篇博客；6. 每天写20+行代码。</summary><published>2011-12-30T07:34:00Z</published><updated>2011-12-30T07:34:00Z</updated><author><name>bengxia</name><uri>http://www.cnblogs.com/bengxia/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bengxia/archive/2011/12/30/2307588.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bengxia/archive/2011/12/30/2307588.html"/><content type="html">&lt;p&gt;1. 每月读1本书；&lt;/p&gt;&#xD;
&lt;p&gt;2. 每天背20个单词；&lt;/p&gt;&#xD;
&lt;p&gt;3. 每周锻炼身体3次；&lt;/p&gt;&#xD;
&lt;p&gt;4. 每天练习口语40分钟；&lt;/p&gt;&#xD;
&lt;p&gt;5.&amp;nbsp;每月写5篇博客；&lt;/p&gt;&#xD;
&lt;p&gt;6. 每天写20+行代码。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/bengxia/aggbug/2307588.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bengxia/archive/2011/12/30/2307588.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bengxia/archive/2011/12/28/2304978.html</id><title type="text">Silverlight + WCF + Sharepoint（Silverlight Web Part） 问题集合</title><summary type="text">“找不到类型{..} 它在 ServiceHost 指令中提供为 Service 特性值，或在配置元素 system.serviceModel/serviceHostingEnvironment/serviceActivations 中提供。” 确认.svc文件中的&amp;lt;%@ ServiceHost Language=&amp;quot;C#&amp;quot; Debug=&amp;quot;true&amp;quot; Service=&amp;quot;{ServiceName}&amp;quot; CodeBehind=&amp;quot;....cs&amp;quot; %&amp;gt;的{ServiceName}是不是跟Web.config中的服务</summary><published>2011-12-28T08:22:00Z</published><updated>2011-12-28T08:22:00Z</updated><author><name>bengxia</name><uri>http://www.cnblogs.com/bengxia/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bengxia/archive/2011/12/28/2304978.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bengxia/archive/2011/12/28/2304978.html"/><content type="html">&lt;ol&gt;&#xD;
&lt;li&gt;&lt;span&gt;&amp;ldquo;找不到类型{..} 它在 ServiceHost 指令中提供为 Service 特性值，或在配置元素 system.serviceModel/serviceHostingEnvironment/serviceActivations 中提供。&amp;rdquo;&lt;/span&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;&lt;span&gt;　　确认.svc文件中的&lt;span&gt;&amp;lt;%@ ServiceHost Language="C#" Debug="true" Service="{ServiceName}" CodeBehind="....cs" %&amp;gt;的{ServiceName}是不是跟Web.config中的服务名称一致。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;/li&gt;&#xD;
&lt;li&gt;&amp;ldquo;&lt;span&gt;自定义工具警告:&amp;nbsp;&lt;/span&gt;&lt;em&gt;没有找到与Silverlight&lt;/em&gt;&lt;span&gt;&amp;nbsp;4&amp;nbsp;&lt;/span&gt;&lt;em&gt;兼容的端点&lt;/em&gt;&lt;span&gt;。生成的客户端类将不可用，&lt;/span&gt;&lt;span&gt;除非通过构造函数提供端点信息。&lt;/span&gt;&amp;rdquo;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;　　WCF是否启用了Silverlight支持？WCF有WCF服务，WCF数据服务，在Silverlight中还有启用Silverlight支持的WCF，靠。&lt;/li&gt;&#xD;
&lt;li&gt;　　[配置服务引用...]，取消选择[重新使用引用的程序集中的类型]。&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;/li&gt;&#xD;
&lt;li&gt;发布到Sharepoint中的Silverlight调用外域的WCF服务&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;　　将添加WCF服务时生成的Reference.cs从Service References移动到项目文件夹下，可以重命名。&lt;/li&gt;&#xD;
&lt;li&gt;　　修改...Client代码：&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;EndpointAddress endPointAddress = new EndpointAddress("{wcf uri}");&#xD;
            CustomBinding binding = new CustomBinding();&#xD;
            binding.Elements.Add(new BinaryMessageEncodingBindingElement());&#xD;
            binding.Elements.Add(new HttpTransportBindingElement());&#xD;
&#xD;
            Adomd.AnalysisService.AdomdConnectorClient client = new Adomd.AnalysisService.AdomdConnectorClient(binding, endPointAddress);&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;注意：如果不使用CutomBinding而用BasicHttpBinding就会返回：Not Found错误，主要是协议的问题，这是跟踪HTTP请求时发现的。&lt;/p&gt;&#xD;
&lt;/li&gt;&#xD;
&lt;li&gt;　　在WCF宿主目录下（跟web.config一起）添加跨域策略文件clientaccesspolicy.xml：&lt;/li&gt;&#xD;
&lt;li&gt;&#xD;
&lt;div &gt;&#xD;
&lt;pre &gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&#xD;
&amp;lt;access-policy&amp;gt;&#xD;
    &amp;lt;cross-domain-access&amp;gt;&#xD;
        &amp;lt;policy&amp;gt;&#xD;
            &amp;lt;allow-from http-request-headers="*"&amp;gt;&#xD;
                &amp;lt;domain uri="*"/&amp;gt;&#xD;
            &amp;lt;/allow-from&amp;gt;&#xD;
            &amp;lt;grant-to&amp;gt;&#xD;
                &amp;lt;resource path="/" include-subpaths="true"/&amp;gt;&#xD;
            &amp;lt;/grant-to&amp;gt;&#xD;
        &amp;lt;/policy&amp;gt;&#xD;
    &amp;lt;/cross-domain-access&amp;gt;&#xD;
&amp;lt;/access-policy&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;/li&gt;&#xD;
&lt;li&gt;挖坑ing...&lt;/li&gt;&#xD;
&lt;/ol&gt;&lt;img src="http://www.cnblogs.com/bengxia/aggbug/2304978.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bengxia/archive/2011/12/28/2304978.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bengxia/archive/2010/07/02/1769958.html</id><title type="text">CLR Via C# 3rd 阅读摘要 -- Chapter 29 – Hybrid Thread Synchronization Constructs</title><summary type="text">    本章讲述的是混合的线程同步模式，首先通过一个简单的例子演示了如何混合使用用户模式和核心模式的同步结构。然后说明了轮转、线程所有制、锁递归的概念。接着列举了几种混合同步结构的实例，并进行了分析比较。本章还讨论了一个非常有意思的问题：单例模式的两次检查加锁情况，给出了正确实现单例模式的方法。然后讲了什么是条件变量模式，以及如何通过使用集合、Task和线程池来避免长时间持有锁。最后简单说明了四个并发集合类。</summary><published>2010-07-02T06:53:00Z</published><updated>2010-07-02T06:53:00Z</updated><author><name>bengxia</name><uri>http://www.cnblogs.com/bengxia/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bengxia/archive/2010/07/02/1769958.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bengxia/archive/2010/07/02/1769958.html"/><content type="html">&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;A Simple Hybrid Lock&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;混合结构在没有竞争的情况下，提供了原生用户模式同步结构的性能优点。同时在有竞争的情况下，提供了核心模式同步结构不浪费CPU资源的优点； &lt;/li&gt;&#xD;
     &lt;li&gt;SimpleHybridLock：&#xD;
     &lt;pre &gt;internal sealed class SimpleHybridLock : IDisposable {&#xD;
     // The Int32 is used by the primitive user-mode constructs (Interlocked methods)&#xD;
     private Int32 m_waiters = 0;&#xD;
     // The AutoResetEvent is the primitive kernel-mode construct&#xD;
     private AutoResetEvent m_waiterLock = new AutoResetEvent(false);&#xD;
     public void Enter() {&#xD;
     // Indicate that this thread wants the lock&#xD;
     if (Interlocked.Increment(ref m_waiters) == 1)&#xD;
     return; // Lock was free, no contention, just return&#xD;
     // Another thread is waiting. There is contention, block this thread&#xD;
     m_waiterLock.WaitOne(); // Bad performance hit here&#xD;
     // When WaitOne returns, this thread now has the lock&#xD;
     }&#xD;
     public void Leave() {&#xD;
     // This thread is releasing the lock&#xD;
     if (Interlocked.Decrement(ref m_waiters) == 0)&#xD;
     return; // No other threads are blocked, just return&#xD;
     // Other threads are blocked, wake 1 of them&#xD;
     m_waiterLock.Set(); // Bad performance hit here.&#xD;
     }&#xD;
     }&lt;/pre&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Spinning, Thread Ownership, and Recursion&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;AnotherHybridLock：&#xD;
     &lt;pre &gt;internal sealed class AnotherHybridLock : IDisposable {&#xD;
     // The Int32 is used by the primitive user-mode constructs (Interlocked methods)&#xD;
     private Int32 m_waiters = 0;&#xD;
     // The AutoResetEvent is the primitive kernel-mode construct&#xD;
     private AutoResetEvent m_waiterLock = new AutoResetEvent(false);&#xD;
     // This field controls spinning in an effort to improve performance&#xD;
     private Int32 m_spinCount = 4000; // Arbitrarily chosen count&#xD;
     // These fields indicate which thread owns the lock and how many times it owns it&#xD;
     private Int32 m_owningThreadId = 0, m_recursion = 0;&#xD;
     public void Enter() {&#xD;
     // If calling thread already owns the lock, increment recursion count and return&#xD;
     Int32 threadId = Thread.CurrentThread.ManagedThreadId;&#xD;
     if (threadId == m_owningThreadId) {&#xD;
     m_recursion++;&#xD;
     return;&#xD;
     }&#xD;
     // The calling thread doesn't own the lock, try to get it&#xD;
     SpinWait spinwait = new SpinWait();&#xD;
     for (Int32 spinCount = 0; spinCount &amp;lt; m_spinCount; spinCount++) {&#xD;
     // If the lock was free, this thread got it; set some state and return&#xD;
     if (Interlocked.CompareExchange(ref m_waiters, 1, 0) == 0)&#xD;
     goto GotLock;&#xD;
     // Black magic: give other threads a chance to run&#xD;
     // in hopes that the lock will be released&#xD;
     spinWait.SpinOnce();&#xD;
     }&#xD;
     // Spinning is over and the lock was still not obtained, try one more time&#xD;
     if (Interlocked.Increment(ref m_waiters) &amp;gt; 1) {&#xD;
     // Other threads are blocked and this thread must block too&#xD;
     m_waiterLock.WaitOne(); // Wait for the lock; preformance hit&#xD;
     // When this thread wakes, it owns the lock; set some state and return&#xD;
     }&#xD;
     GotLock:&#xD;
     // When a thread gets the lock, we record its ID and&#xD;
     // indicate that the thread owns the lock once&#xD;
     m_owningThreadId = threadId;&#xD;
     m_recursion = 1;&#xD;
     }&#xD;
     public void Leave() {&#xD;
     // If the calling thread doesn't own the lock, there is a bug&#xD;
     Int32 threadId = Thread.CurrentThread.ManagedThreadId;&#xD;
     if (threadId != m_owningThreadId)&#xD;
     throw new SynchronizationLockException("Lock not owned by calling thread");&#xD;
     // Decrement the recursion count. If this thread still owns the lock, just return&#xD;
     if (--m_recursion &amp;gt; 0)&#xD;
     return;&#xD;
     // If no other threads are blocked, just return&#xD;
     if (Interlocked.Decrement(ref m_waiters) == 0)&#xD;
     return;&#xD;
     // Other threads are bloced, wake 1 of them&#xD;
     m_waiterLock.Set(); // Bad performance hit here&#xD;
     }&#xD;
     }&lt;/pre&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;性能比较参考：&#xD;
     &lt;pre&gt;Incrementing x: 8 Fastest&#xD;
     Incrementing x in Mutex: 50 6x slower&#xD;
     Incrementing x in SimpleSpinLock: 210 26x slower&#xD;
     Incrementing x in SimpleHybridLock: 211 26x slower (similar to SimpleSpinLock)&#xD;
     Incrementing x in AnotherHybridLock: 415	52x slower (due to ownership/recursion)&#xD;
     Incrementing x in SimpleWaitLock: 17,615	2,201x slower&#xD;
     &lt;/pre&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;A Potpourri of Hybrid Constructs&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;System.Threading.ManualResetEventSlim&lt;/strong&gt;，&lt;strong&gt;System.Threading.SemaphoreSlim&lt;/strong&gt;：跟对应的&lt;strong&gt;ManualResetEvent&lt;/strong&gt;, &lt;strong&gt;Semaphore&lt;/strong&gt;很相似，不同点：直到第一次竞争出现，它们将轮转在用户模式并推迟创建内核模式同步结构；另外，&lt;strong&gt;Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)&lt;/strong&gt;方法可以传入超时参数和&lt;strong&gt;CancellationToken&lt;/strong&gt;； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;Monitor&lt;/strong&gt;(关键字&lt;strong&gt;lock&lt;/strong&gt;，在JIT时会使用&lt;strong&gt;Monitor&lt;/strong&gt;)，一个常用的混合模式同步结构类，提供了支持轮转、线程所有权、递归计数的互斥锁； &lt;/li&gt;&#xD;
     &lt;li&gt;每个托管堆上的对象都有一个叫做&amp;#8220;同步块(Sync Block)&amp;#8221;的数据结构跟它相关联，该数据结构具备字段：内核对象、所属线程ID、递归计数、等待线程数量。 &lt;/li&gt;&#xD;
     &lt;li&gt;当CLR初始化时，会分配一个同步块数组。每个托管堆上的对象，都有两个开销字段：类型对象指针(&lt;strong&gt;Type Object Pointer&lt;/strong&gt;)、同步块索引(&lt;strong&gt;Sync Block Index&lt;/strong&gt;) -- 关联到系统同步块数组的索引(-1：不关联任何同步块)；&#xD;
     &lt;br /&gt;&#xD;
     &lt;a href="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter29HybridThreadSynchroni_9E02/figure29-1.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="figure29-1" border="0" alt="figure29-1" src="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter29HybridThreadSynchroni_9E02/figure29-1.png" /&gt;&lt;/a&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;当&lt;strong&gt;Mointer.Enter&lt;/strong&gt;方法被调用后，CLR会在数组中找到一个空闲的同步块，然后设置对象的同步块索引指向同步块。当&lt;strong&gt;Monitor.Exit&lt;/strong&gt;被调用后，CLR会检查是否有其他线程在等待使用对象的同步块。如果没有，同步块被释放，对象的Sync Block Index被设置成-1； &lt;/li&gt;&#xD;
     &lt;li&gt;同步块可以被关联到类型对象，类型对象的引用可以传递给&lt;strong&gt;Monitor&lt;/strong&gt;的方法； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;Monitor.Enter(&lt;em&gt;this&lt;/em&gt;), .Exit(&lt;em&gt;this&lt;/em&gt;)&lt;/strong&gt;，这里会出现一个比较晦涩的BUG，this所代表的对象在外部可能会被作为锁，这样就不能正常工作，所以&lt;strong&gt;总是使用一个私有锁代替&lt;/strong&gt;，&#xD;
     &lt;pre&gt;private readonly Object m_lock = new Object();&#xD;
     ...&#xD;
     Monitor.Enter(m_lock);&#xD;
     ...&#xD;
     Monitor.Exit(m_lock);&#xD;
     &lt;/pre&gt;&#xD;
     ； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;Monitor&lt;/strong&gt;是一个静态类，所以存在一些问题需要注意：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;如果对象的类型指向&lt;strong&gt;System.MarshalByRefObject&lt;/strong&gt;类型的子类，一个变量可以引用到一个代理对象。当通过传递代理对象的引用调用&lt;strong&gt;Monitor&lt;/strong&gt;的方法时，锁住的是代理对象，而不是实际对象； &lt;/li&gt;&#xD;
         &lt;li&gt;如果一个线程调用&lt;strong&gt;Monitor.Enter&lt;/strong&gt;时，传递一个以及域中立加载的类型对象的引用，线程给进程中所有AppDomain中的该类型上锁。这是一个BUG，所&lt;strong&gt;以绝不使用类型对象的引用调用&lt;strong&gt;Monitor&lt;/strong&gt;的方法&lt;/strong&gt;； &lt;/li&gt;&#xD;
         &lt;li&gt;因为Monitor的方法使用Object做参数，所以传递一个值类型会引起装箱操作。这样锁住的是装箱之后的对象，所以一切同步都白搭； &lt;/li&gt;&#xD;
         &lt;li&gt;使用&lt;strong&gt;[MethodImpl(MethodImplOptions.Synchronized)]&lt;/strong&gt;属性到一个方法上，会引起JIT编译器使用&lt;strong&gt;Monitor.Enter&lt;/strong&gt;和&lt;strong&gt;Monitor.Exit&lt;/strong&gt;包转在本地代码上，如果该方法是个实例方法，那么&lt;strong&gt;this&lt;/strong&gt;就是&lt;strong&gt;Monitor&lt;/strong&gt;方法的参数，锁住的是隐式的公共锁(可能是个噩梦)。如果该方法是静态方法，那么类型的类型对象就是&lt;strong&gt;Monitor&lt;/strong&gt;方法的参数，那就噩梦连绵了。所以，&lt;strong&gt;绝不要使用在方法上使用&lt;strong&gt;[MethodImpl(MethodImplOptions.Synchronized)]&lt;/strong&gt;属性&lt;/strong&gt; &lt;/li&gt;&#xD;
         &lt;li&gt;当调用类型的类型构造器(静态构造器)，CLR在类型的类型对象上加锁以确定只有一个线程初始化该类型对象和它的静态字段。建议：尽可能的避免类型构造器，或者保证它短小精干。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;lock&lt;/strong&gt;会引入&lt;strong&gt;Monitor&lt;/strong&gt;和&lt;strong&gt;try/finally&lt;/strong&gt;块，而JIT不会内联编译带有&lt;strong&gt;try&lt;/strong&gt;块的方法，这会导致降低性能。所以一般不推荐使用lock关键字； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;ReaderWriterLockSlim, OneManyLock, CountdownEvent, Barrier, ...&lt;/strong&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;建议写代码时，别阻塞所有的线程，尽可能短的持有锁； &lt;/li&gt;&#xD;
     &lt;li&gt;读写锁通常比&lt;strong&gt;Monitor&lt;/strong&gt;要慢，但是允许多个读线程并发执行，改善了整体性能，同时最小化了线程阻塞的可能； &lt;/li&gt;&#xD;
     &lt;li&gt;避免使用递归锁(特别是读写递归锁)，因为太糟蹋性能了； &lt;/li&gt;&#xD;
     &lt;li&gt;避免在&lt;strong&gt;finally&lt;/strong&gt;中释放锁，因为进入和离开异常处理块会有性能负担。尤其是在改变状态时出现了异常，那么会导致无法预知的行为，并出现安全漏洞； &lt;/li&gt;&#xD;
     &lt;li&gt;面向计算方向的工作，还是使用&lt;strong&gt;task&lt;/strong&gt;； &lt;/li&gt;&#xD;
     &lt;li&gt;面向I/O方向的工作，采用APM在I/O操作完成后调用回调方法； &lt;/li&gt;&#xD;
     &lt;li&gt;可以使用&lt;strong&gt;SpinLock&lt;/strong&gt;代替&lt;strong&gt;Monitor&lt;/strong&gt;因为&lt;strong&gt;SpinLock&lt;/strong&gt;稍微快一点，但是&lt;strong&gt;SpinLock&lt;/strong&gt;可能会浪费CPU。&lt;strong&gt;Monitor&lt;/strong&gt;实际上也挺快，因为使用本地代码实现的，而不是托管代码； &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;The Famous Double-Check Locking Technique&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;延迟初始化，单例对象知道应用程序使用它才开始初始化，节约时间和内存。潜在问题会出现在当多个线程同时首次访问该对象时； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html" target="_blank"&gt;The "Double-Checked Locking is Broken" Declaration&lt;/a&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;不幸的Java两次检查锁单例代码&lt;/strong&gt;，如果编译器进行优化或者共享内存的多处理器环境下，下面的代码不会正常工作，原因有一大箩筐。&#xD;
     &lt;pre &gt;// Broken multithreaded version&#xD;
     // "Double-Checked Locking" idiom&#xD;
     class Foo {&#xD;
     private Helper helper = null;&#xD;
     public Helper getHelper() {&#xD;
     if (helper == null)&#xD;
     synchronized(this) {&#xD;
     if (helper == null)&#xD;
     helper = new Helper();&#xD;
     }&#xD;
     return helper;&#xD;
     }&#xD;
     // other functions and members...&#xD;
     }&lt;/pre&gt;&#xD;
     简单的办法，使用静态字段：&#xD;
     &lt;pre &gt;class HelperSingleton {&#xD;
     static Helper singleton = new Helper();&#xD;
     }&lt;/pre&gt;&#xD;
     或者，使用JDK5的新语法,&lt;strong&gt;volatile&lt;/strong&gt;关键字:&#xD;
     &lt;pre &gt;// Works with acquire/release semantics for volatile&#xD;
     // Broken under current semantics for volatile&#xD;
     class Foo {&#xD;
     private volatile Helper helper = null;&#xD;
     public Helper getHelper() {&#xD;
     if (helper == null) {&#xD;
     synchronized(this) {&#xD;
     if (helper == null)&#xD;
     helper = new Helper();&#xD;
     }&#xD;
     }&#xD;
     return helper;&#xD;
     }&#xD;
     }&lt;/pre&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;CLR支持Double-Checked Locking，C#版：&#xD;
     &lt;pre &gt;internal sealed class Singleton {&#xD;
     private static readonly Object s_lock = new Object();&#xD;
     private static Singleton s_value = null;&#xD;
     private Singleton() {&#xD;
     }&#xD;
     public static Singleton GetSingleton() {&#xD;
     if (s_value != null) return s_value;&#xD;
     Monitor.Enter(s_lock);&#xD;
     if (s_value == null) {&#xD;
     Singleton temp = new Singleton();&#xD;
     Interlocked.Exchange(ref s_value, temp);&#xD;
     }&#xD;
     Monitor.Exit(s_lock);&#xD;
     return s_value;&#xD;
     }&#xD;
     }&lt;/pre&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;其实，这才是&lt;strong&gt;最实用的单例模式&lt;/strong&gt;：&#xD;
     &lt;pre &gt;internal sealed class Singleton {&#xD;
     private static Singleton s_value = new Singleton();&#xD;
     private Singleton() {&#xD;
     }&#xD;
     public static Singleton GetSingleton() { return s_value; }&#xD;
     }&lt;/pre&gt;&#xD;
     因为CLR在代码第一次尝试访问类的成员时，会自动调用类型的类构造器(class initializer, type initializer, static initializer)。线程第一次调用Singleton.GetSingletonk静态方法时，CLR自动调用类构造器(注意&lt;strong&gt;Before-Field-Init&lt;/strong&gt;语义)，创建出一个该对象的实例。并且：&lt;strong&gt;CLR保证调用类型构造器是线程安全的&lt;/strong&gt;。 &lt;/li&gt;&#xD;
     &lt;li&gt;上面的代码有一点点遗憾，如果Singleton中有其他静态成员，如果任何一个被访问时，Singleton对象就会被创建，这可能并不是所想要的。那么下面的代码简单实用高效可靠：&#xD;
     &lt;pre &gt;internal sealed class Singleton {&#xD;
     private static Singleton s_value = null;&#xD;
     private Singleton() {&#xD;
     }&#xD;
     public static Singleton GetSingleton() {&#xD;
     if (s_value != null) return s_value;&#xD;
     Singleton temp = new Singleton();&#xD;
     Interlocked.CompareExchange(ref s_value, temp, null);&#xD;
     return s_value;&#xD;
     }&#xD;
     }&lt;/pre&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;System.Lazy&lt;t&gt;&lt;/t&gt;&lt;/strong&gt;，&lt;strong&gt;System.Threading.LazyInitializer&lt;/strong&gt;的静态方法，延迟加载和延迟初始化。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;The Condition Variable Pattern&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;当满足一组复杂的条件时，线程执行特定的代码，否则不停轮转检测条件，这通常会浪费CPU时间，&lt;strong&gt;条件变量模式&lt;/strong&gt;(&lt;em&gt;condition variable pattern&lt;/em&gt;)可以基于复杂条件有效的进行同步操作； &lt;/li&gt;&#xD;
     &lt;li&gt;简单的条件变量模式例子：&#xD;
     &lt;pre &gt;internal sealed class ConditionVariablePattern {&#xD;
     private readonly Object m_lock = new Object();&#xD;
     private Boolean m_condition = false;&#xD;
     public void Thread1() {&#xD;
     Monitor.Enter(m_lock);&#xD;
     while (!m_condition) {&#xD;
     Monitor.Wait(m_lock);&#xD;
     }&#xD;
     Monitor.Exit(m_lock);&#xD;
     }&#xD;
     public void Thread2() {&#xD;
     Monitor.Enter(m_lock);&#xD;
     m_condition = true;&#xD;
     Monitor.PulseAll(m_lock);&#xD;
     Monitor.Exit(m_lock);&#xD;
     }&#xD;
     }&lt;/pre&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;线程安全的队列：&#xD;
     &lt;pre &gt;internal sealed class SynchronizedQueue&amp;lt;T&amp;gt; {&#xD;
     private readonly Object m_lock = new Object();&#xD;
     private readonly Queue&amp;lt;T&amp;gt; m_queue = new Queue&amp;lt;T&amp;gt;();&#xD;
     public void Enqueue(T item) {&#xD;
     Monitor.Enter(m_lock);&#xD;
     m_queue.Enqueue(item);&#xD;
     // After enqueuing an item, wake up any/all waiters;&#xD;
     Monitor.PulseAll(m_lock);&#xD;
     Monitor.Exit(m_lock);&#xD;
     }&#xD;
     public T Dequeue() {&#xD;
     Monitor.Enter(m_lock);&#xD;
     while (m_queue.Count == 0)&#xD;
     Monitor.Wait(lock);&#xD;
     T item = m_queue.Dequeue();&#xD;
     Monitor.Exit(m_lock);&#xD;
     return item;&#xD;
     }&#xD;
     }&lt;/pre&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Using Collections to Aviod Holding a Lock for a Long Time&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;System.Threading.Tasks&lt;/strong&gt;所提供的往往更适合，为什么呢，比如&lt;strong&gt;Task&lt;/strong&gt;：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;比线程使用更少的内存，创建和销毁的时间更短； &lt;/li&gt;&#xD;
         &lt;li&gt;线程池会根据CPU的情况自动扩容或收缩； &lt;/li&gt;&#xD;
         &lt;li&gt;Task完成一个阶段，执行Task的线程回到线程池，然后线程可以干点其他的事； &lt;/li&gt;&#xD;
         &lt;li&gt;线程池是全局进程可见的，可以更好的调度任务，减少进程中的线程数，同时减少线程上下文切换的开销。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;Reader-Writer锁非常有用。&lt;a href="http://www.wintellect.com/PowerThreading.aspx" target="_blank"&gt;Power Threading&lt;/a&gt;库有个非阻塞的读写类&lt;em&gt;&lt;a href="http://msdn.microsoft.com/en-us/magazine/cc163532.aspx" target="_blank"&gt;ReaderWriterGate&lt;/a&gt;&lt;/em&gt;。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;The Concurrent Collection Classes&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;FCL提供了4个线程安全的集合类型：&lt;strong&gt;System.Collections.Concurrent&lt;/strong&gt;'s &lt;strong&gt;(ConcurrentQueue, ConcurrentStack, ConcurrentDictionary)&lt;/strong&gt;(MSCorLib.DLL), &lt;strong&gt;ConcurrentBag&lt;/strong&gt;(System.DLL)； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;ConcurrentDictionary&lt;/strong&gt;内部使用&lt;strong&gt;Monitor&lt;/strong&gt;； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;ConcurrentQueue, ConcurrentStack&lt;/strong&gt;没有锁，内部使用&lt;strong&gt;Interlocked&lt;/strong&gt;方法来维护集合； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;ConcurrentBag&lt;/strong&gt;内部由每个线程一个迷你集合容器组成； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;ConcurrentStack, ConcurrentQueue, ConcurrentBag, .GetEnumerator&lt;/strong&gt;方法返回集合内容的快照； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;ConcurrentDictionary.GetEnumerator&lt;/strong&gt;方法不是返回内容的快照，要注意在枚举的过程中元素状态会发生改变。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;本章小结&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;本章讲述的是混合的线程同步模式，首先通过一个简单的例子演示了如何混合使用用户模式和核心模式的同步结构。然后说明了轮转、线程所有制、锁递归的概念。接着列举了几种混合同步结构的实例，并进行了分析比较。本章还讨论了一个非常有意思的问题：单例模式的两次检查加锁情况，给出了正确实现单例模式的方法。然后讲了什么是条件变量模式，以及如何通过使用集合、Task和线程池来避免长时间持有锁。最后简单说明了四个并发集合类。&lt;/p&gt;&#xD;
&lt;img src="http://www.cnblogs.com/bengxia/aggbug/1769958.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bengxia/archive/2010/07/02/1769958.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bengxia/archive/2010/07/01/1768923.html</id><title type="text">CLR Via C# 3rd 阅读摘要 -- Chapter 28 – Primitive Thread Synchronization Constructs</title><summary type="text">    本章讲述了原生的线程同步结构，首先介绍了类库和线程安全性概念，然后对线程同步模式进行了分类：用户模式与核心模式，接着详细说明了这两种同步模式的实现细节，并举例进行了对比。</summary><published>2010-07-01T02:55:00Z</published><updated>2010-07-01T02:55:00Z</updated><author><name>bengxia</name><uri>http://www.cnblogs.com/bengxia/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bengxia/archive/2010/07/01/1768923.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bengxia/archive/2010/07/01/1768923.html"/><content type="html">&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Class Libraries and Thread Safety&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;线程同步是用来避免多个线程同时访问共享数据时出现冲突； &lt;/li&gt;    &lt;li&gt;线程同步的障碍：      &lt;ul&gt;       &lt;li&gt;1.极其乏味易错； &lt;/li&gt;        &lt;li&gt;2.锁严重影响性能； &lt;/li&gt;        &lt;li&gt;3.线程同步锁在同一时间点仅允许一个线程访问资源。 &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;设计程序时应该尽可能的避免线程同步，最好避免采用&lt;strong&gt;static&lt;/strong&gt;字段的共享数据； &lt;/li&gt;    &lt;li&gt;尝试使用值类型，因为它们总是拷贝传递的，因此每个线程在自身拥有的拷贝上操作。所以当多个线程同时以&lt;strong&gt;只读方式&lt;/strong&gt;访问值类型共享数据时是安全的。 &lt;/li&gt;    &lt;li&gt;FCL保证所有的&lt;strong&gt;静态方法&lt;/strong&gt;是线程安全的； &lt;/li&gt;    &lt;li&gt;当一个线程构造一个对象，只有该线程拥有该对象的引用，其他线程不能访问该对象； &lt;/li&gt;    &lt;li&gt;类型设计时应遵循的模式：确保所有的静态方法多线程安全、所有的实例方法多线程不安全；      &lt;br /&gt;一个例外：如果实例方法是用于协调多线程的，那么该实例方法也应该多线程安全。如&lt;strong&gt;CancellationTokenSource.Cancel&lt;/strong&gt;方法。 &lt;/li&gt; &lt;/ol&gt;  &lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Primitive User-Mode and Kernel-Mode Constructs&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;两种原生线程同步结构：      &lt;ul&gt;       &lt;li&gt;用户模式：速度很快，使用特定的CPU指令协调线程，协调工作由硬件完成。Windows系统不会检测线程是否阻塞在用户模式同步结构；          &lt;br /&gt;线程池线程阻塞在用户模式同步结构不会被当成阻塞，线程池不会创建新的线程来代替临时阻塞的线程。           &lt;br /&gt;采用该模式的线程会被系统抢占调度，可能导致线程被反复快速调度，从而会浪费CPU； &lt;/li&gt;        &lt;li&gt;核心模式：Windows操作系统提供，调用实现在系统内核的函数。当一个线程使用内核模式同步结构来请求其他线程持有的资源，Windows将阻塞该线程所以不会浪费CPU；          &lt;br /&gt;线程在用户模式与核心模式间互相转换会严重损害性能； &lt;/li&gt;        &lt;li&gt;如果一个线程持有一个同步结构不再释放它，等待该结构的线程将永远被阻塞：          &lt;ul&gt;           &lt;li&gt;活锁：如果该同步结构是&lt;strong&gt;用户模式&lt;/strong&gt;，线程一直运行在CPU上； &lt;/li&gt;            &lt;li&gt;死锁：如果该同步结构是&lt;strong&gt;核心模式&lt;/strong&gt;，线程被阻塞住； &lt;/li&gt;         &lt;/ul&gt;       &lt;/li&gt;        &lt;li&gt;活锁与死锁都很糟糕，但相比之下，活锁更糟糕，因为活锁既浪费CPU又浪费内存，而死锁只浪费内存； &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;User-Mode Constructs&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;原生的用户模式结构：      &lt;ul&gt;       &lt;li&gt;易变(&lt;strong&gt;volatile&lt;/strong&gt;)结构：在一个简单数据类型变量上执行原子&lt;strong&gt;读或写&lt;/strong&gt;操作； &lt;/li&gt;        &lt;li&gt;联锁(&lt;strong&gt;Interlocked&lt;/strong&gt;)结构：在一个简单数据类型变量上执行原子&lt;strong&gt;读和写&lt;/strong&gt;操作； &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;易变结构确认读或写操作是否原子的非常重要，它们还控制这些原子操作的时机。联锁结构执行操作要比简单的读和写操作复杂一些，它们也需要控制操作的时机； &lt;/li&gt;    &lt;li&gt;比如一个Int64的变量如果没有正确对齐，那么当多线程读写该变量时，可能会出现只正确读取前四字节或后四字节，这就是脏读(&lt;em&gt;torn read&lt;/em&gt;)？ &lt;/li&gt;    &lt;li&gt;System.Threading.Thread&lt;strong&gt;.VolatileWrite&lt;/strong&gt;(), &lt;strong&gt;.VolatileRead&lt;/strong&gt;(), &lt;strong&gt;.MemoryBarrier&lt;/strong&gt;()静态方法通常禁止C#编译器、JIT编译器、CPU进行优化； &lt;/li&gt;    &lt;li&gt;当线程通过共享数据进行通信时，对最后一个值的写操作调用&lt;strong&gt;VolatileWrite&lt;/strong&gt;()，对第一个值的读操作调用&lt;strong&gt;VolatileRead&lt;/strong&gt;()； &lt;/li&gt;    &lt;li&gt;C# &lt;strong&gt;volatile&lt;/strong&gt;关键字：JIT编译器会对标记为volatile的字段的读写进行&lt;strong&gt;VolatileWrite&lt;/strong&gt;()和&lt;strong&gt;VolatileRead&lt;/strong&gt;()处理； &lt;/li&gt;    &lt;li&gt;将来，C#不支持通过引用传递&lt;strong&gt;volatile&lt;/strong&gt;字段到方法调用中； &lt;/li&gt;    &lt;li&gt;现在，&lt;strong&gt;Interlocked.Exchange&lt;/strong&gt;(), &lt;strong&gt;.CompareExchange&lt;/strong&gt;()只支持简单值类型，将来还会提供对&lt;strong&gt;Object&lt;/strong&gt;, &lt;strong&gt;IntPtr&lt;/strong&gt;, &lt;strong&gt;Single&lt;/strong&gt;, &lt;strong&gt;Double&lt;/strong&gt;以及泛型版本的支持； &lt;/li&gt;    &lt;li&gt;SimpleSpinLock的缺陷，当锁出现竞争时，线程会不停轮转，浪费CPU资源：      &lt;pre &gt;internal struct SimpleSpinLock {&#xD;
    private Int32 m_ResourceInUse;  //0 = false (default), 1 = true&#xD;
    &#xD;
    public void Enter() {&#xD;
        // Set the resource to in-use and if this thread&#xD;
        // changed it from Free, then return&#xD;
        while (Interlocked.Exchange(ref m_ResourceInUse, 1) != 0) {&#xD;
            // Black Magic goes here...&#xD;
        }&#xD;
    }&#xD;
    &#xD;
    public void Leave() {&#xD;
        // Mark the resource as Free&#xD;
        Thread.VolatileWrite(ref m_ResourceInUse, 0);&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
  &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;FCL提供的&lt;strong&gt;System.Threading.SpinWait&lt;/strong&gt;； &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;&lt;strong&gt;Thread.Sleep&lt;/strong&gt;(),允许线程资源放弃时间片，休眠时间是近似值； &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;&lt;strong&gt;Thread.Yield&lt;/strong&gt;(),告诉Windows在当前CPU上调度其他线程。如果当前CPU上有其他线程，返回true并结束调用线程的时间片，被调度线程结束自身的时间片之后，调用线程继续。 &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;&lt;strong&gt;Thead.SpinWait&lt;/strong&gt;(),线程强制自己暂停，允许超线程CPU切换到其他线程。该方法会使用特别的CPU指令，如果CPU不支持超线程，该指令被忽略； &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;Win32 API：&lt;strong&gt;Sleep&lt;/strong&gt;(), &lt;strong&gt;SwitchToThread&lt;/strong&gt;(), &lt;strong&gt;YieldProcessor&lt;/strong&gt;()； &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;当集合中的每一项都需要关联锁的时候，轻量级、内存友好的&lt;strong&gt;SpinLock&lt;/strong&gt;是个好东西。但是要注意不要传递它的实例，因为是值类型，传递的是拷贝； &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Kernel-Mode Constructs&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;ol&gt;&#xD;
  &lt;li&gt;核心模式的同步结构比用户模式的要慢许多，因为它们由Windows操作系统协调，此外每个核心对象上的方法调用都会导致调用线程从托管代码转换到本地用户模式代码再到本地核心模式代码，然后再原路返回； &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;核心模式同步结构提供哪些用户模式所没有的优点： &#xD;
    &lt;ul&gt;&#xD;
      &lt;li&gt;当核心模式同步结构检测到资源上出现竞争时，Windows阻塞竞争失败的线程，因此不再浪费处理器资源； &lt;/li&gt;&#xD;
&#xD;
      &lt;li&gt;核心模式同步结构可以同步本地线程和托管线程； &lt;/li&gt;&#xD;
&#xD;
      &lt;li&gt;核心模式同步结构可以同步运行在同一台机器上不同处理器上的线程； &lt;/li&gt;&#xD;
&#xD;
      &lt;li&gt;核心模式同步结构可以附上安全限制避免未经认证的帐号访问他们； &lt;/li&gt;&#xD;
&#xD;
      &lt;li&gt;线程能够被阻塞直到所有的核心模式同步结构都可用，或者任何一个可用； &lt;/li&gt;&#xD;
&#xD;
      &lt;li&gt;阻塞在核心模式同步结构上的线程可以设置一个timeout值；如果这段时间内没能获得期望的资源，那么不再阻塞以干点其他正事。 &lt;/li&gt;&#xD;
    &lt;/ul&gt;&#xD;
  &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;原生的核心模式结构： &#xD;
    &lt;ul&gt;&#xD;
      &lt;li&gt;事件(Events)：事件是有内核管理的&lt;strong&gt;Boolean&lt;/strong&gt;变量。当事件为&lt;strong&gt;false&lt;/strong&gt;时，线程被阻塞。有两种事件：&lt;strong&gt;AutoResetEvent&lt;/strong&gt;、&lt;strong&gt;ManualResetEvent&lt;/strong&gt;； &lt;/li&gt;&#xD;
&#xD;
      &lt;li&gt;信号量(Semaphore)：信号量是内核管理的&lt;strong&gt;Int32&lt;/strong&gt;变量。当信号量为&lt;strong&gt;0&lt;/strong&gt;时，线程被阻塞；&lt;strong&gt;&amp;gt;0&lt;/strong&gt;时，线程不被阻塞。 &lt;/li&gt;&#xD;
    &lt;/ul&gt;&#xD;
  &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;核心模式结构的层次结构： &#xD;
    &lt;pre&gt;WaitHandle&#xD;
  |--EventWaitHandle&#xD;
  |--|--AutoResetEvent&#xD;
  |--|--ManualResetEvent&#xD;
  |--Semaphore&#xD;
  |--Mutex&lt;/pre&gt;&#xD;
  &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;每个在核心模式同步结构上的方法调用都会出现完全内存保护； &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;&lt;strong&gt;SimpleWaitLock&lt;/strong&gt; vs &lt;strong&gt;SimpleSpinLock&lt;/strong&gt;： &#xD;
&#xD;
    &lt;br /&gt;当锁上没有竞争时，&lt;strong&gt;SimpleWaitLock&lt;/strong&gt;比&lt;strong&gt;SimpleSpinLock&lt;/strong&gt;要慢许多，因为&lt;strong&gt;SimpleWaitLock&lt;/strong&gt;的&lt;strong&gt;Enter&lt;/strong&gt;和&lt;strong&gt;Leave&lt;/strong&gt;方法会强制调用线程在托管代码到核心代码之间进行来回转换； &#xD;
&#xD;
    &lt;br /&gt;但是当锁上有竞争时，&lt;strong&gt;SimpleWaitLock&lt;/strong&gt;不会浪费CPU资源，而&lt;strong&gt;SimpleSpinLock&lt;/strong&gt;会不停的轮转CPU； &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;&lt;strong&gt;AutoResetEvent&lt;/strong&gt;、&lt;strong&gt;ManualResetEvent&lt;/strong&gt;、&lt;strong&gt;Semaphore&lt;/strong&gt;行为比较： &#xD;
&#xD;
    &lt;ul&gt;&#xD;
      &lt;li&gt;当多个线程在&lt;strong&gt;AutoResetEvent&lt;/strong&gt;上等待时，设置事件只会让&lt;strong&gt;一个线程&lt;/strong&gt;不再被阻塞； &lt;/li&gt;&#xD;
&#xD;
      &lt;li&gt;当多个线程在&lt;strong&gt;ManualResetEvent&lt;/strong&gt;上等待时，设置事件会让&lt;strong&gt;所有线程&lt;/strong&gt;不再被阻塞； &lt;/li&gt;&#xD;
&#xD;
      &lt;li&gt;当多个线程在&lt;strong&gt;Semaphore&lt;/strong&gt;上等待时，释放信号量会让&lt;strong&gt;releaseCount&lt;/strong&gt;个线程不再被阻塞&lt;strong&gt;(relaseCount&lt;/strong&gt;是&lt;strong&gt;Semaphore.Release&lt;/strong&gt;()方法的参数)。 &lt;/li&gt;&#xD;
    &lt;/ul&gt;&#xD;
  &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;互斥体(Mutex)表现为一个同斥锁； &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;&lt;strong&gt;Mutex&lt;/strong&gt;很像&lt;strong&gt;AutoResetEvent&lt;/strong&gt;或者&lt;strong&gt;Semaphore(count = 1)&lt;/strong&gt;，但有一些更复杂的逻辑： &#xD;
&#xD;
    &lt;ul&gt;&#xD;
      &lt;li&gt;首先，&lt;strong&gt;Mutex&lt;/strong&gt;对象通过查询调用线程的&lt;strong&gt;ID&lt;/strong&gt;记录了哪个线程获得了它。当线程调用&lt;strong&gt;ReleaseMutex&lt;/strong&gt;，&lt;strong&gt;Mutex&lt;/strong&gt;会确认是否为同一线程； &lt;/li&gt;&#xD;
&#xD;
      &lt;li&gt;其次，&lt;strong&gt;Mutex&lt;/strong&gt;维护一个递归计数指出被获得了多少次。只有当递归计数降为&lt;strong&gt;0&lt;/strong&gt;时，其他线程才能获取。 &lt;/li&gt;&#xD;
    &lt;/ul&gt;&#xD;
  &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;Mutex对象需要更多的内存，并且需要维护额外信息，所以会比较慢； &lt;/li&gt;&#xD;
&#xD;
  &lt;li&gt;如何当一个单独的核心结构可用时调用方法？使用&lt;strong&gt;System.Threading.ThreadPool.RegisterWaitForSingleObject&lt;/strong&gt;静态方法。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;本章小结&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;本章讲述了原生的线程同步结构，首先介绍了类库和线程安全性概念，然后对线程同步模式进行了分类：用户模式与核心模式，接着详细说明了这两种同步模式的实现细节，并举例进行了对比。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/bengxia/aggbug/1768923.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bengxia/archive/2010/07/01/1768923.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bengxia/archive/2010/07/01/1768820.html</id><title type="text">FIX: Unable to find a version of the runtime to run this application.</title><summary type="text">How to fix : “.Net Framework Initialization Error  -- Unable to find a version of the runtime to run this application.”</summary><published>2010-07-01T01:06:00Z</published><updated>2010-07-01T01:06:00Z</updated><author><name>bengxia</name><uri>http://www.cnblogs.com/bengxia/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bengxia/archive/2010/07/01/1768820.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bengxia/archive/2010/07/01/1768820.html"/><content type="html">&lt;p&gt;1. [发现问题] 安装Articulate Presenter '09之后，打开时报错：Unable to find a version of the runtime to run this application. 错误标题是：.Net Framework Initialization Error。 &lt;/p&gt;  &lt;p&gt;2. [分析问题] 从错误提示来看，应该是.NET CLR版本兼容性的问题，我的机器上安装了VS2010，所以CLR应该是v4。而系统是Windows 7 64bit，应该自带了CLR v2，Presenter &amp;#8217;09可能不支持v4使用Visual Studio 2010 SDK的命令：ClrVer.exe验证了一下： &lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;D:\Program Files (x86)\Microsoft Visual Studio 10.0\VC&amp;gt;clrver Versions installed on the machine: &lt;/p&gt;    &lt;p&gt;v2.0.50727 &lt;/p&gt;    &lt;p&gt;v4.0.30319 &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;3. [解决问题] 解决问题出人意料的顺利：在目标文件Presenter.exe所在的目录新建配置文件Presenter.exe.config：&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;&amp;lt;configuration&amp;gt;     &lt;br /&gt;&amp;nbsp; &amp;lt;startup&amp;gt;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;supportedRuntime version="v2.0.50727"/&amp;gt;      &lt;br /&gt;&amp;nbsp; &amp;lt;/startup&amp;gt;      &lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;img src="http://www.cnblogs.com/bengxia/aggbug/1768820.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bengxia/archive/2010/07/01/1768820.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bengxia/archive/2010/06/22/1762708.html</id><title type="text">CLR Via C# 3rd 阅读摘要 -- Chapter 27 – I/O-Bound Asynchronous Operations</title><summary type="text">    本章详细讲述了I/O方向的异步工作如何完成，首先解释了Windows处理同步I/O和异步I/O的内部机制。然后介绍了APM，针对APM的问题还介绍了一个Wintellect的辅助类AsyncEnumerator。接着讲了APM如何处理异常，以及应用程序如何选择线程模型。演示了如何实现一个异步的服务器程序(ASP.NET WEB服务、ASP.NET窗体页面、WCF)。解释了APM还可以用于计算方向的异步操作。接着，重点解释了APM的缺点以及处理办法。然后讲述了I/O请求的优先级，以及如何讲了IAsyncResult APM转换成Task。接着还介绍了一种不太优雅的异步编程模型EAP。最后针对几种异步编程模型进行了比较。</summary><published>2010-06-22T07:28:00Z</published><updated>2010-06-22T07:28:00Z</updated><author><name>bengxia</name><uri>http://www.cnblogs.com/bengxia/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bengxia/archive/2010/06/22/1762708.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bengxia/archive/2010/06/22/1762708.html"/><content type="html">&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;How Windows Performs I/O Operations&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;Windows如何处理同步I/O操作？ &lt;br /&gt;&#xD;
     &lt;a href="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter27IOBoundAsynchronousOp_8F2D/figure27-1.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="figure27-1" border="0" alt="figure27-1" src="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter27IOBoundAsynchronousOp_8F2D/figure27-1.png" /&gt;&lt;/a&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;IRP：I/O Request Packet； &lt;/li&gt;&#xD;
     &lt;li&gt;当硬件设备执行I/O操作时，发出I/O请求的线程无事可做，Windows会让该线程休眠所以并不会浪费CPU； &lt;/li&gt;&#xD;
     &lt;li&gt;Windows如何处理异步I/O操作？ &lt;br /&gt;&#xD;
     &lt;a href="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter27IOBoundAsynchronousOp_8F2D/figure27-2.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="figure27-2" border="0" alt="figure27-2" src="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter27IOBoundAsynchronousOp_8F2D/figure27-2.png"  /&gt;&lt;/a&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;.NET异步文件I/O，注意要有FileOptions.Asynchronous，然后调用BeginRead()； &lt;/li&gt;&#xD;
     &lt;li&gt;完成的IRP从线程池中使用FIFO算法抽取； &lt;/li&gt;&#xD;
     &lt;li&gt;当线程完成它的工作并返回到线程池中，线程池不会让它马上处理新的工作项直到CPUs再次饱和之后，因此减少了上下文切换而改进了性能。如果线程池稍后确定拥有的线程比实际需要的多，它会让这些多余的线程自行终结，回收这些线程占有的资源； &lt;/li&gt;&#xD;
     &lt;li&gt;在CLR内部，线程池使用Windows资源&lt;a href="http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx" target="_blank"&gt;I/O Completion Ports&lt;/a&gt;来实现异步I/O行为； &lt;/li&gt;&#xD;
     &lt;li&gt;SilverLight版本的FCL没有提供同步I/O操作，因为在浏览器进程中运行的缘故。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;The CLR's Asynchronous Programming Model(APM)&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;FCL中支持的APM的类型：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;所有和硬件设备通讯的继承自System.IO.Stream的提供BeginWrite()和BeginRead()方法的类型；&lt;strong&gt;注意那些继承自System.IO.Stream但是不跟硬件设备通讯的类型，比如MemoryStream等，也提供了适合APM的BeginWrite()和BeginRead()方法，但是这些方法执行的是计算相关的操作，而不是I/O相关的操作，因此需要请求一个线程来执行计算相关的操作，而I/O相关的操作要少一个线程；&lt;/strong&gt; &lt;/li&gt;&#xD;
         &lt;li&gt;System.Net.Dns提供了BeginGetHostAddress(), BeginGetHostByName(), BeginGetHostEntry(), BeginResolve()； &lt;/li&gt;&#xD;
         &lt;li&gt;System.Net.Sockets.Socket类提供BeginAccept(), BeginConnect(), BeginDisconnect(), BeginReceive(), BeginReceiveFrom(), BeginReceiveMessageFrom(), BeginSend(), BeginSendFile(), BeginSendTo()； &lt;/li&gt;&#xD;
         &lt;li&gt;所有继承自System.Net.WebRequest的类型，提供了BeginGetRequestStream(), BeginGetResponse()方法； &lt;/li&gt;&#xD;
         &lt;li&gt;Sytem.IO.Ports.SerialPort有一个只读属性BaseStream，有BeginRead()和BeginWrite()方法； &lt;/li&gt;&#xD;
         &lt;li&gt;System.Data.SqlClient.SqlCommand类提供了BeginExecuteQuery(), BeginExecuteReader(), BeginExecuteXmlReader()。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;每个BeginXxx()方法都有两个额外的参数:userCallback(:AsyncCallback委托类型)、stateObject(任何希望发送到userCallback的对象引用，在回调函数中，通过参数(IAsyncResult接口)的只读属性AsyncState来获得)； &lt;/li&gt;&#xD;
     &lt;li&gt;当调用BeginXxx()方法时，首先构造出一个唯一的对象标识出I/O请求，然后将该I/O请求加入到Windows设备驱动的队列中，接着返回一个IAsyncResult对象的引用。可以把这个对象看成是你异步调用的凭据。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;The AsyncEnumerator Class&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;APM的麻烦之处：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;必须分隔代码到多个回调方法中； &lt;/li&gt;&#xD;
         &lt;li&gt;必须避免使用参数和本地变量，因为这些变量没有分配在栈空间上，所以不能被其他线程和方法访问； &lt;/li&gt;&#xD;
         &lt;li&gt;有些C#的代码结构中，比如&lt;strong&gt;try/catch/finally, using, for, do, while, foreach&lt;/strong&gt;不能被使用； &lt;/li&gt;&#xD;
         &lt;li&gt;有些特性比较难以实现，比如协调多个并发操作，支持取消和超时，通知GUI线程刷新控件等。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;a href="http://wintellect.com/PowerThreading.aspx" target="_blank"&gt;AsyncEnumerator&lt;/a&gt;可以解决这些APM的麻烦，提供的特性有：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;和现有的.NET技术简便集成； &lt;/li&gt;&#xD;
         &lt;li&gt;协调多个异步并发操作； &lt;/li&gt;&#xD;
         &lt;li&gt;支持分组取消； &lt;/li&gt;&#xD;
         &lt;li&gt;通过调用每个操作的EndXxx()方法自动取消一组异步操作，如果不关心结果的话； &lt;/li&gt;&#xD;
         &lt;li&gt;从烦心应用程序的线程模型中解放出来； &lt;/li&gt;&#xD;
         &lt;li&gt;异常处理支持； &lt;/li&gt;&#xD;
         &lt;li&gt;调试支持。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;The APM and Exceptions&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;HTTP(RFC 2616)申明客户端应用最多同时两个并发线程连接服务器。但是现在很多浏览器和服务器已经没有这个限制了； &lt;/li&gt;&#xD;
     &lt;li&gt;如何在设计服务器程序时解除两个并发线程同时连接的限制：调整&lt;strong&gt;System.Net.ServicePointManager.DefaultConnectionLimit&lt;/strong&gt;属性。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Applications and Their Threading Models&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;GUI程序只允许创建窗体的线程更新界面控件； &lt;/li&gt;&#xD;
     &lt;li&gt;当线程池线程开始处理客户端请求，可以假设客户端的文化特性，允许Web服务器返回文化特定的数字、日期、时间等； &lt;/li&gt;&#xD;
     &lt;li&gt;通过查询GUI线程的.SynchronizationContext.Current属性，可以获得一个SynchronizationContext的引用，可以将该引用保存在共享变量中。这样无论什么时候需要GUI线程修改UI时，就可以让线程池线程引用保存的对象并调用Post方法，将该引用通过将要被GUI线程激发的方法。 &lt;/li&gt;&#xD;
     &lt;li&gt;推荐使用&lt;strong&gt;Post&lt;/strong&gt;(内部BeginInvoke())方法，它将回调压入到GUI线程的队列并允许线程池线程立即返回。而&lt;strong&gt;Send&lt;/strong&gt;内部Invoke()方法，不会立即返回，会被阻塞； &lt;/li&gt;&#xD;
     &lt;li&gt;ASP.NET Web窗体和XML Web服务程序，处理客户端请求开始运行的线程，会有一个继承自&lt;strong&gt;SynchronzationContext&lt;/strong&gt;的对象跟它相关联。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Implementing a Server Asynchronously&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;如何实现异步的ASP.NET Web窗体页面，在.aspx文件的头部加入Page指示"Async=true"。然后在代码中调用&lt;strong&gt;AddOnPreRenderCompleteAsync&lt;/strong&gt;方法； &lt;/li&gt;&#xD;
     &lt;li&gt;如何实现异步的ASP.NET Web服务，提供两个方法BeginXxx(),EndXxx()，并加上属性标签&lt;strong&gt;[WebMethod]&lt;/strong&gt;； &lt;/li&gt;&#xD;
     &lt;li&gt;如何实现异步的WCF Web服务，定义符合模式的BeginXxx(), EndXxx()方法，然后用&lt;strong&gt;[OperationContract(AsyncPattern=true)]&lt;/strong&gt;属性标签标记BeginXxx()。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;The APM and Compute-Bound Operations&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;I/O请求会压入到Windows设备驱动的队列中。然而，委托的BeingInvoke方法通过内部调用&lt;strong&gt;TheadPool.QueueUserWorkItem()&lt;/strong&gt;将计算方向的操作压入到CLR的线程池队列。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;APM Considerations&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li 使用="使用"&gt;APM要注意的问题：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;不通过线程池使用APM；&#xD;
         &lt;ul&gt;APM提供三种途径来知晓异步操作是否完成：&#xD;
             &lt;li&gt;线程在操作完成之前传入IAsyncResult对象调用EndXxx()； &lt;/li&gt;&#xD;
             &lt;li&gt;一个线程可以被阻塞等待其他操作完成，通过调用WaitOne()(IAsyncResult.AsyncWaitHandle)； &lt;/li&gt;&#xD;
             &lt;li&gt;线程可以连续的查询IAsyncResult.IsCompleted属性。 &lt;/li&gt;&#xD;
         &lt;/ul&gt;&#xD;
         &lt;/li&gt;&#xD;
         &lt;li&gt;总是调用EndXxx()方法，并只调用一次。否则会有资源泄露；&#xD;
         &lt;ul&gt;要求调用EndXxx()有两个原因：&#xD;
             &lt;li&gt;当你初始化一个异步操作时CLR会分配一些内部资源。当操作完成后，CLR会持有这些资源知道EndXxx()被调用； &lt;/li&gt;&#xD;
             &lt;li&gt;当初始化一个异步操作，你实际上并不知道该操作最终是成功还是失败。发现问题的唯一途径是调用EndXxx()查询返回值或者检查异常。 &lt;/li&gt;&#xD;
         &lt;/ul&gt;&#xD;
         &lt;/li&gt;&#xD;
         &lt;li&gt;调用EndXxx()方法时总是使用同样的对象； &lt;br /&gt;&#xD;
         当调用BeginInvoke时，IAsyncResult对象内部会持有一个引用到最初对象。 &lt;/li&gt;&#xD;
         &lt;li&gt;在调用BeginXxx()和EndXxx()方法时使用ref, out和params参数； &lt;/li&gt;&#xD;
         &lt;li&gt;不能取消一个异步的I/O方向的操作； &lt;/li&gt;&#xD;
         &lt;li&gt;内存消耗：如果你知道所要执行的I/O操作能够很快完成，那么以同步方式执行更合适； &lt;/li&gt;&#xD;
         &lt;li&gt;有些I/O操作必须以同步方式完成。比如Win32的&lt;strong&gt;CreateFile&lt;/strong&gt;(调用&lt;strong&gt;FileStream&lt;/strong&gt;的构造器)总是以同步方式执行； &lt;br /&gt;&#xD;
         Windows Vista，微软引入了新的Win32函数&lt;strong&gt;CancelSynchronousIO&lt;/strong&gt;()。该函数允许线程取消一个被其他线程执行的同步I/O操作。 &lt;br /&gt;&#xD;
         Windows没有提供异步访问注册表、访问系统事件日志、获得目录/子目录、修改文件/目录的属性、&amp;#8230;&amp;#8230;的函数。 &lt;/li&gt;&#xD;
         &lt;li&gt;FileStream特定的问题。 &lt;br /&gt;&#xD;
         &lt;strong&gt;FileOptions.Asynchronous&lt;/strong&gt;标志(等效于Win32的&lt;strong&gt;CreateFile&lt;/strong&gt;的&lt;strong&gt;FILE_FLAG_OVERLAPPED&lt;/strong&gt;标志)：如果没有指定该标志，Windows以同步方式执行所有的文件操作。当然，仍然可以调用FileStream.BeginRead()方法，看上去操作以异步方式执行，但在内部，FileStream使用另外的线程来模拟异步操作。 &lt;br /&gt;&#xD;
         当使用FileStream，必须确定是以同步还是异步方式执行，也就是&lt;strong&gt;FileOptions.Asynchronous&lt;/strong&gt;标志。如果指定该标志，总是调用&lt;strong&gt;BeginRead()&lt;/strong&gt;，如果不指定，总是调用&lt;strong&gt;Read()&lt;/strong&gt;。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;I/O Request Priorities&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;低优先级的线程获得时间后，可以在短时间内排队大量的I/O请求，所以呢低优先级的线程可能会挂起高优先级的线程，从而严重影响系统的响应性； &lt;/li&gt;&#xD;
     &lt;li&gt;关于I/O优先级，可以从这里&lt;a href="http://www.microsoft.com/whdc/driver/priorityio.mspx" target="_blank"&gt;下载I/O Prioritization in Windows Vista白皮书&lt;/a&gt;； &lt;/li&gt;&#xD;
     &lt;li&gt;相关的Win32 API：GetCurrentProcess、GetCurrentThread、CancelSynchronousIo； &lt;/li&gt;&#xD;
     &lt;li&gt;进程只能影响他自己的后台处理模式；Windows不允许线程修改其他进程的后台处理模式； &lt;/li&gt;&#xD;
     &lt;li&gt;优先级反转：低优先级的线程在正常优先级的线程等待时抢得了线程同步锁，正常优先级的线程可能最终等待后台优先级的线程直到低优先级I/O请求完成。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Converting the IAsyncResult APM to a Task&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;I/O-Bound 从APM转换到Task： &lt;br /&gt;&#xD;
     &lt;strong&gt;APM 代码片段：&lt;/strong&gt; &lt;br /&gt;&#xD;
     &lt;pre &gt;WebRequest webRequest = WebRequest.Create("http://wintellect.com");&#xD;
     webRequest.BeginGetResponse(result =&amp;gt; {&#xD;
     WebResponse webResponse = null;&#xD;
     try {&#xD;
     webResponse = webRequest.EndGetRespone(result);&#xD;
     Console.WriteLine("Content Length: " + webResponse.ContentLength);&#xD;
     }&#xD;
     catch (WebException we) {&#xD;
     Console.WriteLine("Failed: " + we.GetBaseException().Message);&#xD;
     }&#xD;
     finally {&#xD;
     if (webResponse != null) webResponse.Close();&#xD;
     }&#xD;
     }, null);&lt;/pre&gt;&#xD;
     &lt;strong&gt;Task 代码片段：&lt;/strong&gt;&#xD;
     &lt;br /&gt;&#xD;
     &lt;pre &gt;WebRequest webRequest = WebRequest.Create("http://wintellect.com");&#xD;
     Task.Factory.FromAsync&amp;lt;WebResponse&amp;gt;(&#xD;
     webRequest.BeginGetResponse, webRequest.EndGetRespone, null, TaskCreationOptions.None)&#xD;
     .ContinueWith(task =&amp;gt; {&#xD;
     WebResponse webResponse = null;&#xD;
     try {&#xD;
     webResponse = task.Result;&#xD;
     Console.WriteLine("Content Length: " + webResponse.ContentLength);&#xD;
     }&#xD;
     catch (AggregateException ae) {&#xD;
     if (ae.GetBaseException() is WebException)&#xD;
     Console.WriteLine("Failed: " + ae.GetBaseException().Message);&#xD;
     else&#xD;
     throw;&#xD;
     }&#xD;
     finally {&#xD;
     if (webResponse != null) webResponse.Close();&#xD;
     }&#xD;
     });&lt;/pre&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;The Event-Based Asynchronous Pattern&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;EAP：Event-based Asynchronous Pattern； &lt;/li&gt;&#xD;
     &lt;li&gt;BackgroundWorker是设计用来处理计算方向的异步工作的，别错误的用来完成I/O方向的异步工作。I/O方向的比计算方向的异步操作可以少一个线程； &lt;/li&gt;&#xD;
     &lt;li&gt;BackgroundWorker提供三个(EAP)事件：&lt;strong&gt;DoWork、ProgressChanged、RunWorkerCompleted&lt;/strong&gt;； &lt;/li&gt;&#xD;
     &lt;li&gt;将EAP转换成Task：&lt;strong&gt;System.Threading.Tasks.TaskCompletionSource&lt;/strong&gt;； &lt;/li&gt;&#xD;
     &lt;li&gt;比较APM和EAP：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;EAP比APM最大的优点就是Visual Studiao设计时支持。GUI程序，事件处理方法由GUI线程激发； &lt;/li&gt;&#xD;
         &lt;li&gt;EAP内部以APM方式实现，需要更多的内存并且执行速度相对较慢。实际上，EAP必须为所有的过程报告和完成事件分配多个继承自EventArg的对象； &lt;/li&gt;&#xD;
         &lt;li&gt;以后，静态方法和单例类不再能提供EAP，因为：程序的不同部分可以立刻注册所有的事件，当操作完成时，程序的不同部分无论是否异步操作都需要激发事件处理方法； &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;EAP一般用于窗体程序，而且由于有额外开销，虽然在设计器上可以方便使用，但是还是不建议使用。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Programming Model Soup&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;比较：QueueUserWorkItem、Timer、RegisterWaitForSingleObject、Tasks、IAsyncResult APM、Event-based PM、AsyncEnumerator；&#xD;
     &lt;br /&gt;&#xD;
     &lt;a href="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter27IOBoundAsynchronousOp_8F2D/table27-1.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="table27-1" border="0" alt="table27-1" src="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter27IOBoundAsynchronousOp_8F2D/table27-1.png"/ /&gt;&lt;/a&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;Tasks比&lt;strong&gt;QueueUserWorkItem&lt;/strong&gt;或委托的&lt;strong&gt;BeginInvoke&lt;/strong&gt;性能更好； &lt;/li&gt;&#xD;
     &lt;li&gt;对于&lt;strong&gt;ThreadPool.QueueUserWorkItem&lt;/strong&gt;或委托的&lt;strong&gt;BeginInvoke&lt;/strong&gt;，使用PreFairness标志可以获得相同的线程池行为； &lt;/li&gt;&#xD;
     &lt;li&gt;可以定制TaskScheduler，可以改变调度算法而不需要改变代码或编程模型； &lt;/li&gt;&#xD;
     &lt;li&gt;Task对象比&lt;strong&gt;QueueUserWorkItem&lt;/strong&gt;或委托的&lt;strong&gt;BeginInvoke&lt;/strong&gt;会消费更多的内存； &lt;/li&gt;&#xD;
     &lt;li&gt;IAsyncResult APM提供了四种技术，模型比较复杂，但是如果少使用回调方法技术，模型就简单多了； &lt;/li&gt;&#xD;
     &lt;li&gt;支持EAP的类多半都支持取消我行为； &lt;/li&gt;&#xD;
     &lt;li&gt;IAsyncResult APM支持不支持任何取消操作； &lt;/li&gt;&#xD;
     &lt;li&gt;EAP是基于事件的，因此可以简单的用于Windows窗体、WPF、SilverLight窗体设计器。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;本章小结&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;本章详细讲述了I/O方向的异步工作如何完成，首先解释了Windows处理同步I/O和异步I/O的内部机制。然后介绍了APM，针对APM的问题还介绍了一个Wintellect的辅助类AsyncEnumerator。接着讲了APM如何处理异常，以及应用程序如何选择线程模型。演示了如何实现一个异步的服务器程序(ASP.NET WEB服务、ASP.NET窗体页面、WCF)。解释了APM还可以用于计算方向的异步操作。接着，重点解释了APM的缺点以及处理办法。然后讲述了I/O请求的优先级，以及如何讲了IAsyncResult APM转换成Task。接着还介绍了一种不太优雅的异步编程模型EAP。最后针对几种异步编程模型进行了比较。&lt;/p&gt;&#xD;
&lt;img src="http://www.cnblogs.com/bengxia/aggbug/1762708.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bengxia/archive/2010/06/22/1762708.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bengxia/archive/2010/06/09/1754614.html</id><title type="text">CLR Via C# 3rd 阅读摘要 -- Chapter 26 – Compute-Bound Asynchronous Operations</title><summary type="text">    本章讲了计算方向的异步操作问题，首先隆重推出了CLR的线程池概念，给线程池的线程划分了两个类别：工作者线程和I/O线程。然后演示了如何简单的使用线程池实现一个多线程计算操作；接着讨论了线程池的线程执行体上下文结构；然后引出了协作式取消模式以解释如何在线程池中取消操作；本章重点讨论了Task，一种使用线程池的更强大易用方法，并演示了如何等待任务完成获得结果，如何取消任务，如何在一个任务完成后自动的开始另外一个任务，如何由一个任务开始子任务。接着分析了Task的实现机制和调度策略，如何利用TaskFactory工厂模式创建任务。本章还讲述了如何使用Parallel LINQ以及它的限制和注意事项；接着还讨论了定时器的作用，比较了FCL提供的几种定时器的差异。之后简单解释了线程池是如何管理线程的。最后讨论了高速缓存行和多处理器环境下需要注意的错误共享(False Sharing)问题。</summary><published>2010-06-09T03:39:00Z</published><updated>2010-06-09T03:39:00Z</updated><author><name>bengxia</name><uri>http://www.cnblogs.com/bengxia/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bengxia/archive/2010/06/09/1754614.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bengxia/archive/2010/06/09/1754614.html"/><content type="html">&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Introducing the CLR's Thread Pool&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;线程池可以看成有一组线程可以被你的应用程序以自有的方式使用； &lt;/li&gt;&#xD;
     &lt;li&gt;每个CLR有一个线程池，这个线程池被该CLR控制的AppDomain共享； &lt;/li&gt;&#xD;
     &lt;li&gt;当CLR初始化时，线程池中没有线程。线程池内部维护一个操作请求的队列； &lt;/li&gt;&#xD;
     &lt;li&gt;线程池最重要的作用是管理拥有多少线程才算合适，少点线程以避免浪费资源，多点线程以发挥多处理器、超线程处理器、多核处理器的优势； &lt;/li&gt;&#xD;
     &lt;li&gt;工作者线程(Worker Threads)用来当应用程序请求线程池来执行异步的计算方向的操作(也可以初始化一个I/O方向的操作)； &lt;/li&gt;&#xD;
     &lt;li&gt;I/O线程(I/O Threads)用来通知你的代码一个异步的I/O操作已经完成； &lt;/li&gt;&#xD;
     &lt;li&gt;APM：Asynchronous Programming Model。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Performing a Simple Compute-Bound Operation&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;TheadPool.QueueUserWorkerItem(WaitCallback callback), .QueueUserWorkerItem(WaitCallback callback, Object state)； &lt;/li&gt;&#xD;
     &lt;li&gt;如果回调方法抛出一个异常没有被处理，CLR终止该进程(除非宿主强制使用自己的策略)。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Execution Contexts&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;每个线程都有一个相关联的执行上下文(Execution Context)数据结构，包括如安全设置(Thread.Principal)、宿主设置(System.Threading.HostExecutionContextManager)、逻辑调用上下文数据(Sytem.Runtime.Remoting.Messaging.CallContext.LogicalSetData(). LogicalSetData())； &lt;/li&gt;&#xD;
     &lt;li&gt;ExecutionContext类允许你控制一个线程的Execution Context从一个线程产生自另一个线程； &lt;/li&gt;&#xD;
     &lt;li&gt;ExecutionContext.SuppressFlow()方法标记有[SecurityCritical]属性，因此一些客户程序(比如SilverLight)不能调用； &lt;/li&gt;&#xD;
     &lt;li&gt;流转包含逻辑调用上下文数据项的执行上下文会戏剧性的影响性能，因为需要序列化/反序列化这些数据项； &lt;/li&gt;&#xD;
     &lt;li&gt;在执行ExecutionContext.SuppressFlow()之后，CallContext.LogicalSetData()设置的上下文数据就不能被访问了。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Cooperative Cancellation&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;合作取消模式，意味着你希望取消的操作必须支持显示的取消行为； &lt;/li&gt;&#xD;
     &lt;li&gt;要在线程池中取消一个操作，必须使用System.Threading.CancellationTokenSource对象。实例化CancellationTokenSource对象后，该实例有一个Token属性； &lt;/li&gt;&#xD;
     &lt;li&gt;可以注册(CancellationToken.Register())一个或多个方法，当一个CancellationTokenSource取消后被调用； &lt;/li&gt;&#xD;
     &lt;li&gt;如何连接多个CancellationTokenSource对象，调用CancellationTokenSource.CreateLinkedTokenSource()静态方法。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Tasks&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;使用ThreadPool.QueueUserWorkerItem()虽然简单，但是有限制，最大的问题是不知道何时操作完成，也没有办法获得返回值； &lt;/li&gt;&#xD;
     &lt;li&gt;更好的解决方案是使用Tasks，System.Threading.Tasks； &lt;/li&gt;&#xD;
     &lt;li&gt;[Flags]public enum TaskCreationOptions {None, PreferFairness, LongRunning, AttachedToParent}； &lt;/li&gt;&#xD;
     &lt;li&gt;等待一个Task完成并获得返回结果：Task.Wait()实例方法, Task.Result属性； &lt;/li&gt;&#xD;
     &lt;li&gt;如果调用了Wait()，但是Task没有开始执行，系统可能(依赖TaskScheduler)使用调用Wait()的线程执行该Task，这样线程调用Wait()不会被阻塞；立即执行Task然后立即返回，这可能会节约资源提高性能，但是可能会造成死锁； &lt;/li&gt;&#xD;
     &lt;li&gt;使用TaskScheduler.UnobservedTaskException静态事件注册回调方法，可以帮组检测未观测到的异常； &lt;/li&gt;&#xD;
     &lt;li&gt;Task.WaitAny()静态方法阻塞调用线程直到数组中的任何Task对象完成； &lt;/li&gt;&#xD;
     &lt;li&gt;Task.WaitAll()静态方法阻塞调用线程直到数组中的所有Task对象完成； &lt;/li&gt;&#xD;
     &lt;li&gt;取消一个Task：Token.ThrowIfCancellationRequested(); &lt;/li&gt;&#xD;
     &lt;li&gt;如果CancellationToken在Task开始之后被调度之前取消，Task不执行就取消。但是如果不开始就取消，会抛出InvalidOperationException异常； &lt;/li&gt;&#xD;
     &lt;li&gt;一旦一个Task对象有CancellationToken关联上，就没有途径访问它，所以你必须以某种方式获得相同的CancellationToken； &lt;/li&gt;&#xD;
     &lt;li&gt;当一个Task完成时自动开始另一个Task：Task.ContinueWith()实例方法； &lt;/li&gt;&#xD;
     &lt;li&gt;[Flags]public enum TaskContinuationOptions {None, PreferFairness, LongRunning, AttachedToParent, ExecuteSynchronously, NotOnRanToCompletion, NotOnFaulted, NotOnCanceled, OnlyOnCanceled, OnlyOnFaulted, OnlyOnRanToCompletion}； &lt;/li&gt;&#xD;
     &lt;li&gt;一个Task开始多个Child Tasks：Task&#xD;
     &lt;tresult&gt;&#xD;
     ；&#xD;
     &lt;/tresult&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;public enum TaskStatus {Created, WaitingForActivation, WaitingToRun, Running, WaitingForChildrenToComplete, RanToCompletion, Canceled, Faulted}; &lt;/li&gt;&#xD;
     &lt;li&gt;TaskFactory&#xD;
     &lt;tresult&gt;&#xD;
     , .StartNew()；&#xD;
     &lt;/tresult&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;两类TaskScheduler：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;线程池任务调度器：默认情况下，所有的应用程序使用线程池任务调度器； &lt;/li&gt;&#xD;
         &lt;li&gt;同步上下文任务调度器：通常用于Windows Forms、WPF、SilverLight等GUI应用； &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;Parallel Extensions Extras包：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;IOTaskScheduler &lt;/li&gt;&#xD;
         &lt;li&gt;LimitedConcurrencyLevelTaskScheduler &lt;/li&gt;&#xD;
         &lt;li&gt;OrderedTaskScheduler &lt;/li&gt;&#xD;
         &lt;li&gt;PrioritizingTaskScheduler &lt;/li&gt;&#xD;
         &lt;li&gt;ThreadPerTaskScheduler &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Parallel's Static For, ForEach, and Invoke Methods&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;如果工作必须以顺序方式完成，那么就不要使用Parallel方法；同样，避免工作项修改任何类型的共享数据，因为如果多个线程同时维护该数据可能会出现问题； &lt;/li&gt;&#xD;
     &lt;li&gt;Parallel.For(), .ForEach(), .Invoke()方法可以接受ParallelObject对象参数； &lt;/li&gt;&#xD;
     &lt;li&gt;Parallel.For(), .ForEach()的重载方法可以传入3个委托：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;任务本地初始化委托(localInit)，在任务请求处理一个工作项前调用； &lt;/li&gt;&#xD;
         &lt;li&gt;主体部分委托(body)，一旦有项目被参与工作的线程处理时被调用； &lt;/li&gt;&#xD;
         &lt;li&gt;任务本地终止委托(localFinally)，任务处理完所有的工作项后调用，即使遇到异常。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Parallel Language Integrated Query&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;使用LINQ，可以简便的进行过滤、排序、投影等操作。但是这些处理过程是顺序的； &lt;/li&gt;&#xD;
     &lt;li&gt;Parallel LINQ，以并行的方式使用LINQ。System.LINQ.ParallelQuery&lt;t&gt;； &lt;/t&gt;&lt;/li&gt;&#xD;
     &lt;li&gt;要使用Parallel LINQ，必须使用ParallelEnumerable.AsParallel()扩展方法从顺序查询(基于IEnumerable或IEnumerable&lt;t&gt;)转换成并行查询(基于ParallelQuery或ParallelQuery&lt;t&gt;)； &lt;/t&gt;&lt;/t&gt;&lt;/li&gt;&#xD;
     &lt;li&gt;如果需要让Parallel LINQ保持处理的顺序，需要调用ParallelEnumerable.AsOrdered()扩展方法； &lt;/li&gt;&#xD;
     &lt;li&gt;以无序方式处理的行为：Distinct, Except, Intersect, Union, Join, GroupBy, GroupJion, ToLookup； &lt;/li&gt;&#xD;
     &lt;li&gt;以有序方式处理的行为：OrderBy, OrderbyDescending, ThenBy, ThenByDescending； &lt;/li&gt;&#xD;
     &lt;li&gt;WithDegreeOfParallelism()方法指定同时处理的最多的线程数量。缺省情况下，线程数量等于CPU核的数量； &lt;/li&gt;&#xD;
     &lt;li&gt;Parallel LINQ会分析查询然后决定如何处理最佳； &lt;/li&gt;&#xD;
     &lt;li&gt;有时候顺序处理会获得最佳性能，比如：Concat, ElementAt(OrDefault), First(OrDefault), Last(OrDefault), Skip(While), Take(While), Zip。以及在选择器(selector)和断言(predicate)委托中含有位置指示的Select(Many)和Where； &lt;/li&gt;&#xD;
     &lt;li&gt;如果你希望强制并行方式处理，可以调用WithExecutionMode()，传入ParallelExecutionMode {Default, ForceParallelism}标志； &lt;/li&gt;&#xD;
     &lt;li&gt;WithMergeOptions()，可以用来控制查询结果集合并缓存，也就是时空权衡，传入ParallelMergeOptions {Default, NoBuffered, AutoBuffered, FullyBuffered}标志； &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Performing a Periodic Compute-Bound Operation&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;System.Threading.Timer，构造时可以有TimerCallback回调参数； &lt;/li&gt;&#xD;
     &lt;li&gt;当一个Timer对象被当作垃圾收集后，它的终止化方法告诉线程池取消该定时器因此不再离开。因此当使用Timer对象时，确定有变量保持Timer对象存活否则你的回调方法将停止调用； &lt;/li&gt;&#xD;
     &lt;li&gt;有很多的定时器，之间有什么差异呢？&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;&lt;strong&gt;System.Threading.Timer&lt;/strong&gt;，最好的定时器，如果要执行间隙性的后台任务，首选它； &lt;/li&gt;&#xD;
         &lt;li&gt;&lt;strong&gt;System.Windows.Forms.Timer&lt;/strong&gt;，类似于Win32的SetTimer函数，当定时器消失时，Windows会插入一个WM_TIMER在线程的消息队列中。不能被多线程同时执行。回调方法的线程必须和设置定时器的线程是同一线程； &lt;/li&gt;&#xD;
         &lt;li&gt;&lt;strong&gt;System.Threading.DispatcherTimer&lt;/strong&gt;，用于WPF和SilverLight，等同于System.Windows.Forms.Timer； &lt;/li&gt;&#xD;
         &lt;li&gt;&lt;strong&gt;&lt;strike&gt;System.Timer.Timer&lt;/strike&gt;&lt;/strong&gt;，唯一的好处就是可以用于在设界面计器上拖拽，除非真的有必要，否则就不要用。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;How the Thread Pool Manages Its Threads&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;线程池的默认最多线程数量是1000，这在32位系统2G的内存地址空间下是比较合理的限制。CLR项目组会进行合理调整，不要自行修改； &lt;/li&gt;&#xD;
     &lt;li&gt;System.Threading.ThreadPool.GetMaxThreads(), .SetMaxThreads(), .GetMinThreads(), .SetMinThreads(), .GetAvailableThreads()； &lt;/li&gt;&#xD;
     &lt;li&gt;CLR的线程池有一个全局队列，每个工作线程有一个本地队列； &lt;br /&gt;&#xD;
     &lt;a href="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter26ComputeBoundAsynchron_C9CF/figure26-1.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="figure26-1" border="0" alt="figure26-1" src="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter26ComputeBoundAsynchron_C9CF/figure26-1.png" /&gt;&lt;/a&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;全局队列采用FIFO算法；本地队列采用LIFO算法。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Cache Lines and False Sharing&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;CPU逻辑上将内存划分为缓存行(cache line)，在64位的机器系统上，一个缓存行包含64字节，因此CPU以64字节块对RAM进行存取； &lt;/li&gt;&#xD;
     &lt;li&gt;因此，如果是64位的机器系统，需要读取Int32的变量，那么包含该变量(4Bytes)的64Bytes的内存块会被读取。读取更多的字节可能会有很好的性能提升，因为大多数应用程序趋向于访问临近的数据，这样数据就很可能已经在Cache中，不需要再从RAM中读取； &lt;/li&gt;&#xD;
     &lt;li&gt;但是，如果如果两核或多核访问的数据在同一个缓存行上，这些CPU核就需要进行协调，反而会极大的对性能造成负面影响； &lt;/li&gt;&#xD;
     &lt;li&gt;Win32的GetProcessorInformation()函数可以获得CPU的缓存行大小； &lt;/li&gt;&#xD;
     &lt;li&gt;[StructLayout(LayoutKind.Explicit)]和[FieldOffest(...)]以缓存行大小递增可以控制字段的布局，以避免需要多线程访问的临近数据不在同一个缓存行上； &lt;/li&gt;&#xD;
     &lt;li&gt;因为内存布局和缓存行的缘故。从程序的观点，两个线程管理不同的数据。但是从CPU的观点，两个CPU核却是管理相同的数据。这叫做：虚假共享(False Sharing)； &lt;/li&gt;&#xD;
     &lt;li&gt;如果这些CPU在不同的NUMA节点上，虚假共享(False Sharing)会对性能造成极其负面的影响； &lt;/li&gt;&#xD;
     &lt;li&gt;要避免虚假共享(False Sharing)，应该避免一个线程写数组的前几个元素而其他的线程在访问数组的其他元素。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;本章小结&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;本章讲了计算方向的异步操作问题，首先隆重推出了CLR的线程池概念，给线程池的线程划分了两个类别：工作者线程和I/O线程。然后演示了如何简单的使用线程池实现一个多线程计算操作；接着讨论了线程池的线程执行体上下文结构；然后引出了协作式取消模式以解释如何在线程池中取消操作；本章重点讨论了Task，一种使用线程池的更强大易用方法，并演示了如何等待任务完成获得结果，如何取消任务，如何在一个任务完成后自动的开始另外一个任务，如何由一个任务开始子任务。接着分析了Task的实现机制和调度策略，如何利用TaskFactory工厂模式创建任务。本章还讲述了如何使用Parallel LINQ以及它的限制和注意事项；接着还讨论了定时器的作用，比较了FCL提供的几种定时器的差异。之后简单解释了线程池是如何管理线程的。最后讨论了高速缓存行和多处理器环境下需要注意的错误共享(False Sharing)问题。&lt;/p&gt;&#xD;
&lt;img src="http://www.cnblogs.com/bengxia/aggbug/1754614.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bengxia/archive/2010/06/09/1754614.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bengxia/archive/2010/06/02/1750027.html</id><title type="text">CLR Via C# 3rd 阅读摘要 -- Chapter 25 – Thread Basics</title><summary type="text">    本章讲述了线程的基本知识。首先介绍了Windows的线程概念，CPU的发展趋势，CLR线程与Windows线程直接的关系。然后分析了使用线程的开销，总结了在什么情况下使用线程，使用线程时要注意哪些问题。接着讲解了NUMA的体系结构。讲述了在什么情形下需用使用确定的线程来完成异步计算密集型任务。接着给出了使用线程的理由。重点深入解释了Windows线程的调度机制，线程的优先级以及和线程优先级之间的关联。本章的结尾讲述了选择前台线程和后台线程的条件。最后还推荐了Wintellect Power Threading Library来简化异步编程和线程同步。</summary><published>2010-06-02T07:34:00Z</published><updated>2010-06-02T07:34:00Z</updated><author><name>bengxia</name><uri>http://www.cnblogs.com/bengxia/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bengxia/archive/2010/06/02/1750027.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bengxia/archive/2010/06/02/1750027.html"/><content type="html">&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Why Does Windows Support Threads?&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;Windows支持线程可以给系统提供更好的健壮性和交互响应； &lt;/li&gt;&#xD;
     &lt;li&gt;Windows一个进程至少有一个主线程，可以启动多个线程，调度单位是线程。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Thread Overhead&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;跟所有的虚拟化机制一样，线程有时间(运行时执行性能)和空间(内存)的额外开销； &lt;/li&gt;&#xD;
     &lt;li&gt;每个线程会包括下列的个别内容：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;线程核心对象：一个数据结构，包括一组描述线程的属性。以及调用的线程的上下文信息(一块内存用来放置CPU的寄存器状态)，x86 CPU (&amp;#8776;700Bytes)，x64 CPU(&amp;#8776;1240Bytes)，IA64 CPU(&amp;#8776;2500Bytes)； &lt;/li&gt;&#xD;
         &lt;li&gt;线程环境块(TEB)：在用户态(应用代码可以快速访问的地址空间)分配和初始化的内存块。TEB消耗一个内存页面，x86/x64 CPUs(4KB)，IA64 CPU(8KB)。包括异常处理链的头，线程进入每一个try块时会在异常处理链的头部插入一个节点。另外TEB还包括线程的线程本地存储数据； &lt;/li&gt;&#xD;
         &lt;li&gt;用户态堆栈：用来存储传到方法的本地变量和参数。Windows默认分配1MB； &lt;/li&gt;&#xD;
         &lt;li&gt;核心态堆栈：当操作系统中应用程序代码传递给核心态函数的参数值。32位系统(12KB)，64位系统(24KB)； &lt;/li&gt;&#xD;
         &lt;li&gt;DLL线程进入离开通知：Windows有一个策略，任何时候进程中创建了线程，所有进程中装载的DLL都会调用DllMain方法，附带DLL_THREAD_ATTACH标志。同样的，在线程结束时，DllMain再次被调用，附带DLL_THREAD_DETACH标志。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;DisableThreadLibraryCalls&lt;/strong&gt;，非托管代码调用该Win32函数可以忽略DLL_THREAD_ATTACH和DLL_THREAD_DETACH通知。C#和其他托管代码开发的DLL没有DllMain所以没有此缺陷； &lt;/li&gt;&#xD;
     &lt;li&gt;上下文切换：分配给线程的CPU时间片配额用完后，Windows会切换到其他线程执行。会执行以下动作：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;1.保存CPU寄存器的值到当前运行的线程的核心对象数据结构中； &lt;/li&gt;&#xD;
         &lt;li&gt;2.从现存的线程集中调度一个线程。如果该线程属于其他进程，Windows还必须切换虚拟地址空间； &lt;/li&gt;&#xD;
         &lt;li&gt;3.从目前调度的线程核心对象数据结构中装载值到寄存器。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;当CPU时间片用完后，Windows可能会调度同一个线程，这种情况下不会执行上下文切换； &lt;/li&gt;&#xD;
     &lt;li&gt;线程可以自愿的提前结束时间片，经常发生在I/O操作(键盘、网络、鼠标、&amp;#8230;&amp;#8230;)完成时； &lt;/li&gt;&#xD;
     &lt;li&gt;当执行垃圾收集时，CLR必须挂起所有的线程完成一系列检查清理操作。因此避免多线程可以极大的改进垃圾收集器的效率； &lt;/li&gt;&#xD;
     &lt;li&gt;当使用Debugger时，Windows也会挂起所有的线程； &lt;/li&gt;&#xD;
     &lt;li&gt;多CPU的计算机可以同时运行多个线程，增加了扩展性； &lt;/li&gt;&#xD;
     &lt;li&gt;Windows保证不会同时将一个线程调度到不同的CPU核上，因为这将引起灾难。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Stop the Madness&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;虽然创建线程的开销比进程小的多，但是跟系统资源比较起来还是很昂贵的，所以应该避免滥用。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;CPU Trends&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;三种主流多CPU技术：一台计算机多片CPU、超线程CPU、多核CPU。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;NUMA Architecture Machines&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;ccNUMA: Cache-Coherent Non-Uniform Memory Access(连续缓存的非均匀存储器存取)。设计用于多处理器的计算机内存，访问内存时依赖于处理器相关的内存定位。在NUMA情况下，处理器访问自有的本地内存要比非本地(其他处理器共享的)内存快很多； &lt;/li&gt;&#xD;
     &lt;li&gt;NUMA的体系结构： &lt;br /&gt;&#xD;
     &lt;a href="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter25ThreadBasics_D748/figure25-3.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="figure25-3" border="0" alt="figure25-3" src="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter25ThreadBasics_D748/figure25-3.png" /&gt;&lt;/a&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;北桥芯片主要决定主板的规格、对硬件的支持、以及系统的性能，它连接着 CPU 、内存、 AGP 总线。主板支持什么 CPU ，支持 AGP 多少速的显卡，支持何种频率的内存，都是北桥芯片决定的。北桥芯片往往有较高的工作频率，所以发热量颇高，我们在主板上，可以在 CPU 插槽附近找到一个散热器，下面的就是北桥芯片。同北桥芯片的主板，性能差别微乎其微； &lt;/li&gt;&#xD;
     &lt;li&gt;南桥芯片主要决定主板的功能，主板上的各种接口（如串口、 USB ）、 PCI 总线（接驳电视卡、内猫、声卡等）、 IDE （接硬盘、光驱）、以及主板上的其他芯片（如集成声卡、集成 RAID 卡、集成网卡等），都归南桥芯片控制。南桥芯片通常裸露在 PCI 插槽旁边，块头比较大； &lt;/li&gt;&#xD;
     &lt;li&gt;一台计算机可以有一个或多个处理器组，每个处理器组有一个或多个NUMA节点，每个NUMA节点包含多个逻辑处理器、高速缓存、本地内存，每个NUMA节点有一个或多个插槽芯片，每个插槽芯片有一个或多个CPU核，每个CPU核包含一个或多个逻辑处理器。Windows 2008支持256个逻辑处理器； &lt;/li&gt;&#xD;
     &lt;li&gt;目前CLR还没有利用处理器组的优点，所有的线程都创建在0组(默认)，并且在64位Windows上最多只支持64核。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;CLR Threads and Windows Threads&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;目前CLR线程直接应射到Windows线程，但是以后未必会这样，CLR有可能引入自己的逻辑线程概念； &lt;/li&gt;&#xD;
     &lt;li&gt;如果需要P/Invoke来最多限度的使用本地代码，使用当前的物理操作系统线程是非常重要的，这需要调用System.Threading.Thread.BeginThreadAffinity()静态方法。当不再需要使用物理线程时，调用Thread.EndThreadAffinity()通知CLR。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Using a Dedicated Thread to Perform an Asynchronous Compute-Bound Operation&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;本节的内容不建议使用，而推荐优先使用CLR的线程池； &lt;/li&gt;&#xD;
     &lt;li&gt;如果要创建自己的线程而不采用线程池，先检查以下条件是否存在：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;线程需要运行在非常规权限下。所有的线程池线程运行在正常权限下； &lt;/li&gt;&#xD;
         &lt;li&gt;需要线程以前台线程方式运行，避免线程完成任务之前应用程序就over了。所有的线程池线程都是后台模式的； &lt;/li&gt;&#xD;
         &lt;li&gt;计算密集任务需要很长时间运行； &lt;/li&gt;&#xD;
         &lt;li&gt;有可能需要提前Abort的线程。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;如果创建带参数的线程，使用System.Threading.Thread(ParameterizedThreadStart start);构造函数，不推荐使用； &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Reasons to Use Threads&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;使用线程的理由：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;隔离代码； &lt;/li&gt;&#xD;
         &lt;li&gt;简化代码； &lt;/li&gt;&#xD;
         &lt;li&gt;并发执行。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;多线程可以充分利用CPU，但是如果想压榨计算机的CPU资源，有两个警告：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;1.如果用电池供电的话，100%的cpu利用会很耗电； &lt;/li&gt;&#xD;
         &lt;li&gt;2.一些数据中心宁愿10台计算机运行在50%的CPU负载，也不愿意5台计算机运行在100%的CPU负载。因为过热需要HVAC降温因此支付更多的电费。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Threading Scheduling and Priorities&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;Windows为什么叫抢占式多线程操作系统，因为任何时候一个线程停止后，另外一个线程可以马上被调度； &lt;/li&gt;&#xD;
     &lt;li&gt;线程的优先级别从0到31级，其中0, 17~30普通开发者不能使用； &lt;/li&gt;&#xD;
     &lt;li&gt;进程优先级(Idle -&amp;gt; Below Normal -&amp;gt; Normal -&amp;gt; Above Normal -&amp;gt; High -&amp;gt; Realtime)与线程优先级(Idle -&amp;gt; Lowest -&amp;gt; Below Normal -&amp;gt; Normal -&amp;gt;Above Normal -&amp;gt; Highest -&amp;gt; Time-Critical)的关联矩阵： &lt;a href="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter25ThreadBasics_D748/table25-1.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="table25-1" border="0" alt="table25-1" src="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter25ThreadBasics_D748/table25-1.png"/ /&gt;&lt;/a&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;CLR中，ThreadPriority枚举只包括{Lowest, Below Normal, Normal, Above Normal, Highest}五种； &lt;/li&gt;&#xD;
     &lt;li&gt;垃圾回收器线程以Time-Critical级别运行； &lt;/li&gt;&#xD;
     &lt;li&gt;System.Diagnotics下面有两个类：Process和ProcessThread，分别提供进程和线程的情况。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Foreground Threads versus Background Threads&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;如果进程中的所有前台线程停止运行，CLR强制结束仍然在运行的后台线程。这些后台线程立即结束，没有异常抛出； &lt;/li&gt;&#xD;
     &lt;li&gt;如果希望线程执行的任务真正完成(比如刷新缓冲数据到物理磁盘)，那么可以使用前台线程； &lt;/li&gt;&#xD;
     &lt;li&gt;如果是无关紧要的任务(比如重新计算工作表)，那么可以使用后台线程； &lt;/li&gt;&#xD;
     &lt;li&gt;创建线程时，默认情况下是前台线程，如何转换成后台线程：Thread t = new Thread(...); t.&lt;strong&gt;IsBackground&lt;/strong&gt; = true; &lt;/li&gt;&#xD;
     &lt;li&gt;一般来说，应该尽可能的避免使用前台线程，因为这可能会阻止进程正常终止。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;What Now?&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;CLR的线程池是应该优先使用的； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;a href="http://wintellect.com/PowerThreading.aspx" target="_blank"&gt;Wintellect Power Threading Library&lt;/a&gt;：可以简化线程同步和异步编程。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;本章小结&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;本章讲述了线程的基本知识。首先介绍了Windows的线程概念，CPU的发展趋势，CLR线程与Windows线程直接的关系。然后分析了使用线程的开销，总结了在什么情况下使用线程，使用线程时要注意哪些问题。接着讲解了NUMA的体系结构。讲述了在什么情形下需用使用确定的线程来完成异步计算密集型任务。接着给出了使用线程的理由。重点深入解释了Windows线程的调度机制，线程的优先级以及和线程优先级之间的关联。本章的结尾讲述了选择前台线程和后台线程的条件。最后还推荐了Wintellect Power Threading Library来简化异步编程和线程同步。&lt;/p&gt;&#xD;
&lt;img src="http://www.cnblogs.com/bengxia/aggbug/1750027.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bengxia/archive/2010/06/02/1750027.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bengxia/archive/2010/05/31/1748259.html</id><title type="text">CLR Via C# 3rd 阅读摘要 -- Chapter 24 – Runtime Serialization</title><summary type="text">   本章讲了序列化和反序列化的知识，序列化可以讲对象转换成流进行传输或者持久化，在需要的时候通过反序列化在将对象构造出来。首先讲了如何让类型具备序列化的能力，以及如何控制序列化的过程。然后讲了Formatter如何序列化类型实例，如何控制序列化/反序列化的数据，介绍了StreamingContext对象，演示了如何将对象反序列化到不同的类型实例。接着介绍了序列化代理，最后讲了SerializationBinder抽象类可以用来反序列化对象到不同的类型。</summary><published>2010-05-31T07:14:00Z</published><updated>2010-05-31T07:14:00Z</updated><author><name>bengxia</name><uri>http://www.cnblogs.com/bengxia/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bengxia/archive/2010/05/31/1748259.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bengxia/archive/2010/05/31/1748259.html"/><content type="html">&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Serialization/Deserialization Quick Start&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;序列化是将一个对象以及相关的对象转换成字节流的过程；反序列化就是序列化的逆过程； &lt;/li&gt;    &lt;li&gt;System.Runtime.Serialization命名空间； &lt;/li&gt;    &lt;li&gt;当序列化一个对象时，Formatter首先抓取程序集标识，并确定程序集通过调用System.Reflection.Assembly.Load()被装载到执行的AppDomain中； &lt;/li&gt;    &lt;li&gt;程序集被装载后，Formatter在程序集中查找待反序列化对象所匹配的类型，然后实例化再根据流来初始化实例的字段； &lt;/li&gt;    &lt;li&gt;一些扩展程序使用Assembly.LoadFrom()来加载程序集，然后从定义在程序集中的类型来构造对象。这些对象在序列化时没有问题，但是反序列化时，Formatter会尝试使用Assembly.Load()来加载程序集，大多数情况下，CLR不能准确定位程序集文件，所以可能会引发SerializationException； &lt;/li&gt;    &lt;li&gt;因为上面的原因，如果使用Assembly.LoadFrom()来加载程序集，那么强烈建议在反序列化之前处理System.AppDomain.AssemblyResolver事件。 &lt;/li&gt; &lt;/ol&gt;  &lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Making a Type Serializable&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;对象在默认情况下是不能序列化的，可以通过给类型加上[Serializable]标签来实现； &lt;/li&gt;    &lt;li&gt;[Serializable]属性不能被子类型所继承； &lt;/li&gt;    &lt;li&gt;System.Object有[Serializable]属性； &lt;/li&gt;    &lt;li&gt;一般来说，推荐大多数类型为可序列化的？(我的看法是那些可能会被跨边界访问的类型)。 &lt;/li&gt; &lt;/ol&gt;  &lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Controlling Serialization and Deserialization&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;至少有两个原因使得你不打算让类型实例的一些字段被序列化：      &lt;ul&gt;       &lt;li&gt;字段的值在反序列化时已经失效了，比如Windows Kernel对象的句柄(文件、进程、线程、互斥体、事件、信号量、&amp;#8230;&amp;#8230;)； &lt;/li&gt;        &lt;li&gt;字段的值可以在反序列化时很简单的重新计算出来。 &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;字段加上[NonSerialized]属性标签可以阻止该字段被序列化； &lt;/li&gt;    &lt;li&gt;如果希望字段在反序列化时被重新计算，可以定义一个方法&lt;strong&gt;[OnDeserialized]private void OnDeserialized(StreamingContext context){...}&lt;/strong&gt;； &lt;/li&gt;    &lt;li&gt;跟[OnDeserialized]相似的几个属性[OnSerializing] -&amp;gt; [OnSerialized] -&amp;gt; [OnDeserializing] -&amp;gt; [OnDeserialized]； &lt;/li&gt;    &lt;li&gt;如果你序列化一个类型的实例，在类型中加入新的字段，然后在尝试反序列化时，Formatter会抛出SerializationException指出成员数目不对，可以通过使用[OptionalField]属性标签来解决该问题。 &lt;/li&gt; &lt;/ol&gt;  &lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;How Formatters Serialize Type Instances&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;FormatterServices.GetSerializableMembers(), .GetObjectData(), GetTypeFromAssembly(), GetUninitializedObject(), .PopulateObjectMembers()静态方法。 &lt;/li&gt; &lt;/ol&gt;  &lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Controlling the Serialized/Deserialized Data&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;如何完全的控制序列化/反序列化，可以实现System.Runtime.Serialization.ISerializable接口； &lt;/li&gt;    &lt;li&gt;一旦类型继承了ISerializable接口，那么子类型也就必须实现该接口； &lt;/li&gt;    &lt;li&gt;建议在GetObjectData方法和特殊构造器上附加[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]属性标签； &lt;/li&gt;    &lt;li&gt;当Formatter在序列化对象图时，先查找每一个对象，如果有一个类型实现了ISerializable接口，Formatter就忽略其他所有的客户属性，并构造一个新的System.Runtime.Serialization.SerializationInfo对象； &lt;/li&gt;    &lt;li&gt;总是调用SerializationInfo.AddValue来加入序列化信息到类型中，如果字段的类型实现了ISerializable接口，别在字段上调用GetObjectData，而是调用AddValue； &lt;/li&gt;    &lt;li&gt;如果类型是sealed，那么强烈建议将特殊构造声明为private； &lt;/li&gt;    &lt;li&gt;如果基类没有实现ISerializable接口，怎样为类型实现该接口？FormatterServices.GetSerializableMembers()。 &lt;/li&gt; &lt;/ol&gt;  &lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Streaming Contexts&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;StreamingContext.State, .Context； &lt;/li&gt;    &lt;li&gt;StreamingContextStates {CrossProcess, CrossMachines, File, Persistence, Remoting, Other, Clone, CrossAppDomain, All}; &lt;/li&gt; &lt;/ol&gt;  &lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Serializing a Type as a Different Type and Deserializing an Object as a Different Object&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Serialization Surrogates&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;System.Runtime.Serialization.ISerializationSurrogate.GetObjectData(), .SetObjectData()； &lt;/li&gt;    &lt;li&gt;BinaryFormatter有一个bug阻止从序列化对象到其他的引用。要解决该问题，需要传一个ISerializationSurrogate对象的引用到FormatterServices.GetSurrogateForCyclicalReference()方法； &lt;/li&gt;    &lt;li&gt;SurrogateSelector.AddSurrogate()，多个SurrogateSelector对象可以被链接起来，SurrogateSelector实现了ISurrogateSelector接口。 &lt;/li&gt; &lt;/ol&gt;  &lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Overriding the Assembly and/or Type When Deserializing an Object&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;System.Runtime.Serialization.SerializationBinder使得反序列化对象到不同的类型非常容易。要做到这点，需要定义的类型继承自抽象类SerializationBinder。 &lt;/li&gt; &lt;/ol&gt;  &lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;本章小结&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;本章讲了序列化和反序列化的知识，序列化可以讲对象转换成流进行传输或者持久化，在需要的时候通过反序列化在将对象构造出来。首先讲了如何让类型具备序列化的能力，以及如何控制序列化的过程。然后讲了Formatter如何序列化类型实例，如何控制序列化/反序列化的数据，介绍了StreamingContext对象，演示了如何将对象反序列化到不同的类型实例。接着介绍了序列化代理，最后讲了SerializationBinder抽象类可以用来反序列化对象到不同的类型。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/bengxia/aggbug/1748259.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bengxia/archive/2010/05/31/1748259.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/bengxia/archive/2010/05/24/1742778.html</id><title type="text">CLR Via C# 3rd 阅读摘要 -- Chapter 23 – Assembly Loading and Reflection</title><summary type="text">    本章讨论了如何构建可动态扩展的应用程序，以及如何通过反射来获得类型信息，创建类型的实例，动态的访问它们的成员。首先介绍了如何加载程序集以及如何通过反射来扩展应用，然后分析了反射会引起的性能问题以及如何减轻影响，然后介绍了构建插件应用程序的途径，最后讲了如何通过反射来调用类型的成员。</summary><published>2010-05-24T06:45:00Z</published><updated>2010-05-24T06:45:00Z</updated><author><name>bengxia</name><uri>http://www.cnblogs.com/bengxia/</uri></author><link rel="alternate" href="http://www.cnblogs.com/bengxia/archive/2010/05/24/1742778.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/bengxia/archive/2010/05/24/1742778.html"/><content type="html">&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Assembly Loading&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;在运行时，JIT编译器使用程序集的TypeDef和AssemblyDef元数据表来确定被引用的类型在哪个程序集中； &lt;/li&gt;&#xD;
     &lt;li&gt;CLR内部尝试使用&lt;strong&gt;System.Reflection.Assembly.Load&lt;/strong&gt;静态方法来装载程序集； &lt;/li&gt;&#xD;
     &lt;li&gt;使用强名称程序集装载时，Load方法会引起CLR应用版本绑定重定向策略(GAC，应用程序根目录，私有路径子目录，代码基位置)。如果是弱名称程序集，Load方法不会应用版本绑定重定向策略，CLR也不会在GAC中查找程序集； &lt;/li&gt;&#xD;
     &lt;li&gt;Load方法string参数的形式："SomeAssembly, Version=2.0.0.0, Culture=neutral, PublicKeyToken=01234567890abcde, ProcessorArchitecutre=MSIL"； &lt;/li&gt;&#xD;
     &lt;li&gt;CLR目前支持的ProcessorArchitecture：MSIL，x86，IA64，AMD64； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;System.AppDomain.Load(...)&lt;/strong&gt; &lt;em&gt;(.net 2.0没有的)&lt;/em&gt;不同于&lt;strong&gt;System.Reflection.Assembly.Load(...)&lt;/strong&gt;，AppDomain.Load是一个实例方法，用来装载一个特定的程序集到指定的AppDomain，该方法是设计用来给非托管代码调用的，它允许一个宿主注入一个程序集到特定的AppDomain中。托管应用中应该避免使用AppDomain.Load方法； &lt;/li&gt;&#xD;
     &lt;li&gt;相关的工具：ILDasm.exe, PEVerify.exe, CorFlags.exe, GACUtil.exe, SGen.exe, SN.exe, XSD.exe； &lt;/li&gt;&#xD;
     &lt;li&gt;如果要指定路径装载程序集，可以使用&lt;strong&gt;Assembly.LoadFrom(...)&lt;/strong&gt;方法，LoadFrom会首先调用&lt;strong&gt;System.Assembly.AssemblyName.GetAssemblyName(...)&lt;/strong&gt;，然后调用Load方法； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;LoadFrom(...)&lt;/strong&gt;可以传入URL作为参数，但是建议使用另一个方法&lt;strong&gt;UnsafeLoadFrom(...)&lt;/strong&gt;； &lt;/li&gt;&#xD;
     &lt;li&gt;Assembly.LoadFile(...)可以多次装载同一个程序集到单独的AppDomain中，但是CLR不会自动解决程序集依赖问题，必须注册AppDomain.AssemblyResolve事件然后在事件回调方法中显示的装载相关的程序集； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;程序集不可以被单独卸载&lt;/strong&gt;，AppDomain才可以； &lt;/li&gt;&#xD;
     &lt;li&gt;将引用的程序集dll作为项目的"嵌入的资源"再编译，可以包装成单独的exe分发，在运行时CLR找不到依赖的dll，这可以通过注册AppDomain.ResolveAssembly事件来解决： &lt;br /&gt;&#xD;
     &lt;pre &gt;AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =&amp;gt; {&#xD;
     String resourceName = "AssemblyLoadingAndReflection." + new AssemblyName(args.Name).Name + ".dll";&#xD;
     using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) {&#xD;
     Byte[] assemblyData = new Byte[stream.Length];&#xD;
     stream.Read(assemblyData, 0, assemblyData.Length);&#xD;
     return Assembly.Load(assemblyData);&#xD;
     }&#xD;
     };&lt;/pre&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Using Reflection to Build a Dynamically Extensible Application&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;System.Reflection&lt;/strong&gt;命名空间，可以用来构建动态扩展的应用程序； &lt;/li&gt;&#xD;
     &lt;li&gt;反射还可以用来在运行时从一个特定的程序集装载特定的类型来完成相关的任务。概念上跟Win32的的&lt;strong&gt;LoadLibrary&lt;/strong&gt;和&lt;strong&gt;GetProcAddress&lt;/strong&gt;方法相似； &lt;/li&gt;&#xD;
     &lt;li&gt;早期绑定(编译时)和后期绑定(运行时)。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Reflection Performance&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;反射的两个主要缺点：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;反射没有提供运行时的类型安全； &lt;/li&gt;&#xD;
         &lt;li&gt;反射的速度很慢。通过反射来调用成员会损坏性能。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;一般情况下应该避免使用反射，如果应用程序需要动态的发现和构造类型实例，可以选择下面两种捷径之一：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;使得类型继承自编译时确定的基类型； &lt;/li&gt;&#xD;
         &lt;li&gt;(&lt;strong&gt;推荐&lt;/strong&gt;)使得类型实现在编译时确定的接口。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;使用上面两种方法时，应该把基类型或接口定义在独立的程序集中，这可以减轻版本问题； &lt;/li&gt;&#xD;
     &lt;li&gt;发现定义在程序集中的类型：&lt;strong&gt;Assembly.GetExportedType(...)&lt;/strong&gt;； &lt;/li&gt;&#xD;
     &lt;li&gt;FLC中，&lt;strong&gt;Sytem.ReflectionOnlyType&lt;/strong&gt; 继承自 &lt;strong&gt;Sytem.RuntimeType&lt;/strong&gt; 继承自 &lt;strong&gt;Sytem.Type&lt;/strong&gt; 继承自 &lt;strong&gt;System.Reflection.MemberInfo&lt;/strong&gt;； &lt;/li&gt;&#xD;
     &lt;li&gt;TypeDelegator用来通过动态的封装Type来子类化一个Type； &lt;/li&gt;&#xD;
     &lt;li&gt;System.RuntimeType是FLC内部使用的，一个类型第一次在AppDomain中访问时，CLR构造一个RuntimeType的实例并初始化对象的字段到反射类型的信息； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;System.Object.GetType()&lt;/strong&gt;实际上会返回一个RuntimeType； &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;typeof&lt;/strong&gt;操作符，通常用来比较早期绑定和晚期绑定的类型信息； &lt;/li&gt;&#xD;
     &lt;li&gt;如何构造一个类型的实例？&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;&lt;strong&gt;System.Activator.CreateInstance(), CreateInstanceFrom();&lt;/strong&gt; &lt;/li&gt;&#xD;
         &lt;li&gt;&lt;strong&gt;System.AppDomain.CreateInstance(), CreateInstanceAndUpwarp(), CreateInstanceFrom(), CreateInstanceFromAndUnwarp(); &lt;/strong&gt;&lt;/li&gt;&#xD;
         &lt;li&gt;&lt;strong&gt;System.Type.InvokeMember();&lt;/strong&gt; &lt;/li&gt;&#xD;
         &lt;li&gt;&lt;strong&gt;System.Reflection.ConstructorInfo.Invoke();&lt;/strong&gt; &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;System.Activator.CreateInstance()允许构造一个值类型而不必调用构造方法； &lt;/li&gt;&#xD;
     &lt;li&gt;数组的动态构造：调用&lt;strong&gt;Array.CreateInstance(...)&lt;/strong&gt;静态方法； &lt;/li&gt;&#xD;
     &lt;li&gt;委托的动态构造：调用&lt;strong&gt;Delegate.CreateInstance(...)&lt;/strong&gt;静态方法； &lt;/li&gt;&#xD;
     &lt;li&gt;泛型类型的动态构造：调用&lt;strong&gt;Type.MakeGenericType(...)&lt;/strong&gt;实例方法。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Designing an Application That Supports Add-Ins&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;当构建一个可扩展的应用程序时，应该以接口为中心点。当然也可以用基类代替接口，但通常接口优先，让插件开发者选择自己选择基类； &lt;/li&gt;&#xD;
     &lt;li&gt;如何设计一个可扩展的应用程序？步骤：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;创建一个宿主SDK程序集，定义方法接口，满足宿主应用和插件之间的通信机制。尽量使用MSCorLib.dll中定义的类型和接口，一旦确定别随意更改； &lt;/li&gt;&#xD;
         &lt;li&gt;插件开发者，定义自己的类型在插件程序集中； &lt;/li&gt;&#xD;
         &lt;li&gt;创建一个分离的宿主应用程序集包含你应用程序的类型，想干什么就干什么，但是别涉及插件宿主SDK。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;Using Reflection to Discover a Type's Member&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;发现类型的成员，关于类型成员封装信息的反射类型的层次结构:&#xD;
     &lt;br /&gt;&#xD;
     &lt;a href="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter23AssemblyLoadingandRef_80B4/figure23-1.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="figure23-1" border="0" alt="figure23-1" src="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter23AssemblyLoadingandRef_80B4/figure23-1.png" /&gt;&lt;/a&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;&lt;strong&gt;System.Type&lt;/strong&gt;继承自&lt;strong&gt;System.Reflection.MemberInfo&lt;/strong&gt;，&lt;strong&gt;GetMembers()&lt;/strong&gt;方法返回继承自&lt;strong&gt;MemberInfo(EventInfo, FieldInfo, MethodBase(ConstrcutorInfo, MethodInfo), PropertyInfo, Type)&lt;/strong&gt;对象的数组； &lt;/li&gt;&#xD;
     &lt;li&gt;DeclaringType与ReflectedType属性的区别(比如，&lt;strong&gt;public class MyType: Object {public string ToString(){return null;}}&lt;/strong&gt;，typeof(MyType).GetMembers())：&#xD;
     &lt;ul&gt;&#xD;
         &lt;li&gt;DeclaringType:获得定义该成员的类(ToString，返回MyType，Equals，返回Object)； &lt;/li&gt;&#xD;
         &lt;li&gt;ReflectedType:获得用来获得该成员的类对象(ToString, Equals，都返回MyType)。 &lt;/li&gt;&#xD;
     &lt;/ul&gt;&#xD;
     &lt;/li&gt;&#xD;
     &lt;li&gt;反射的对象模型：&#xD;
     &lt;br /&gt;&#xD;
     &lt;a href="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter23AssemblyLoadingandRef_80B4/figure23-2.png" target="_blank"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="figure23-2" border="0" alt="figure23-2" src="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter23AssemblyLoadingandRef_80B4/figure23-2.png" /&gt;&lt;/a&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;如何筛选成员类型：&lt;strong&gt;System.Reflection.BindingFlags&lt;/strong&gt;;Type.GetMembers(), GetNestedTypes(), GetFields(), GetConstructors(), GetMethods(), GetProperties(), GetEvents()；&#xD;
     &lt;br /&gt;&#xD;
     &lt;a href="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter23AssemblyLoadingandRef_80B4/table23-2.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="table23-2" border="0" alt="table23-2" src="http://images.cnblogs.com/cnblogs_com/bengxia/WindowsLiveWriter/CLRViaC3rdChapter23AssemblyLoadingandRef_80B4/table23-2.png" /&gt;&lt;/a&gt; &lt;/li&gt;&#xD;
     &lt;li&gt;发现类型的接口：Type.FindInterfaces(), GetInterface(), GetInterfaces()； &lt;/li&gt;&#xD;
     &lt;li&gt;调用类型的成员，Type.InvokeMember()； &lt;/li&gt;&#xD;
     &lt;li&gt;反射使用CAS(代码访问安全)来确定不被滥用； &lt;/li&gt;&#xD;
     &lt;li&gt;一次绑定，多次调用，提高效率； &lt;/li&gt;&#xD;
     &lt;li&gt;使用绑定句柄(RuntimeTypeHandle, RuntimeFieldHandle, RuntimeMethodHandle)来减少进程的内存开销。 &lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;h1 style="padding-bottom: 5px; background-color: gray; margin-top: 24px; padding-left: 5px; padding-right: 5px; margin-bottom: 12px; color: white; font-size: 26px; font-weight: normal; padding-top: 5px"&gt;&lt;font  size="6" face="Arial"&gt;&lt;span style="font-size: 24px" &gt;本章小结&lt;/span&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;本章讨论了如何构建可动态扩展的应用程序，以及如何通过反射来获得类型信息，创建类型的实例，动态的访问它们的成员。首先介绍了如何加载程序集以及如何通过反射来扩展应用，然后分析了反射会引起的性能问题以及如何减轻影响，然后介绍了构建插件应用程序的途径，最后讲了如何通过反射来调用类型的成员。&lt;/p&gt;&#xD;
&lt;img src="http://www.cnblogs.com/bengxia/aggbug/1742778.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/bengxia/archive/2010/05/24/1742778.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
