ReaderWriterLock(定义支持单个写线程和多个读线程的锁),Mutex(一个同步基元,也可用于进程间同步。 )
 ReaderWriterLock 用于同步对资源的访问。在任一特定时刻,它允许多个线程同时进行读访问,或者允许单个线程进行写访问。在资源不经常发生更改的情况下,ReaderWriterLock 所提供的吞吐量比简单的一次只允许一个线程的锁(如 Monitor)更高。
ReaderWriterLock 用于同步对资源的访问。在任一特定时刻,它允许多个线程同时进行读访问,或者允许单个线程进行写访问。在资源不经常发生更改的情况下,ReaderWriterLock 所提供的吞吐量比简单的一次只允许一个线程的锁(如 Monitor)更高。
 在多数访问为读访问,而写访问频率较低、持续时间也比较短的情况下,ReaderWriterLock 的性能最好。多个读线程与单个写线程交替进行操作,所以读线程和写线程都不会长时间阻止。
在多数访问为读访问,而写访问频率较低、持续时间也比较短的情况下,ReaderWriterLock 的性能最好。多个读线程与单个写线程交替进行操作,所以读线程和写线程都不会长时间阻止。
 一个线程可以持有读线程锁或写线程锁,但是不能同时持有两者。若要获取写线程锁,请使用 UpgradeToWriterLock 和 DowngradeFromWriterLock,而不要通过释放读线程锁的方式获取。
一个线程可以持有读线程锁或写线程锁,但是不能同时持有两者。若要获取写线程锁,请使用 UpgradeToWriterLock 和 DowngradeFromWriterLock,而不要通过释放读线程锁的方式获取。
 递归锁请求会增加锁上的锁计数。
递归锁请求会增加锁上的锁计数。
 读线程和写线程将分别排入各自的队列。当线程释放写线程锁时,此刻读线程队列中的所有等待线程都将被授予读线程锁;当已释放所有读线程锁时,写线程队列中处于等待状态的下一个线程(如果存在)将被授予写线程锁,依此类推。换句话说,ReaderWriterLock 在一组读线程和一个写线程之间交替进行操作。
读线程和写线程将分别排入各自的队列。当线程释放写线程锁时,此刻读线程队列中的所有等待线程都将被授予读线程锁;当已释放所有读线程锁时,写线程队列中处于等待状态的下一个线程(如果存在)将被授予写线程锁,依此类推。换句话说,ReaderWriterLock 在一组读线程和一个写线程之间交替进行操作。
 当写线程队列中有一个线程在等待活动读线程锁被释放时,请求新的读线程锁的线程会排入读线程队列。即使它们能和现有的阅读器锁持有者共享并发访问,也不会给它们的请求授予权限;这有助于防止编写器被阅读器无限期阻止。
当写线程队列中有一个线程在等待活动读线程锁被释放时,请求新的读线程锁的线程会排入读线程队列。即使它们能和现有的阅读器锁持有者共享并发访问,也不会给它们的请求授予权限;这有助于防止编写器被阅读器无限期阻止。
 大多数在 ReaderWriterLock 上获取锁的方法都采用超时值。使用超时可以避免应用程序中出现死锁。例如,某个线程可能获取了一个资源上的写线程锁,然后请求第二个资源上的读线程锁;同时,另一个线程获取了第二个资源上的写线程锁,并请求第一个资源上的读线程锁。如果不使用超时,这两个线程将出现死锁。
大多数在 ReaderWriterLock 上获取锁的方法都采用超时值。使用超时可以避免应用程序中出现死锁。例如,某个线程可能获取了一个资源上的写线程锁,然后请求第二个资源上的读线程锁;同时,另一个线程获取了第二个资源上的写线程锁,并请求第一个资源上的读线程锁。如果不使用超时,这两个线程将出现死锁。
 如果超时间隔过期并且没有授予锁请求,则此方法通过引发 ApplicationException 将控制返回给调用线程。线程可以捕捉此异常并确定下一步要进行的操作。
如果超时间隔过期并且没有授予锁请求,则此方法通过引发 ApplicationException 将控制返回给调用线程。线程可以捕捉此异常并确定下一步要进行的操作。
 超时用毫秒表示。如果使用 System.TimeSpan 指定超时,则所用的值是 TimeSpan 所表示的毫秒整数的总和。下表显示用毫秒表示的有效超时值。
超时用毫秒表示。如果使用 System.TimeSpan 指定超时,则所用的值是 TimeSpan 所表示的毫秒整数的总和。下表显示用毫秒表示的有效超时值。
 值
值  说明
 说明  
  -1
-1  Infinite.
 Infinite.  
  0
0  无超时。
 无超时。  
  > 0
> 0  要等待的毫秒数。
 要等待的毫秒数。  
 
 除了 -1 以外,不允许使用负的超时值。如果要使用 -1 以外的负整数来指定超时,系统将使用零(无超时)。如果指定的 TimeSpan 表示的是 -1 以外的负毫秒数,将引发 ArgumentOutOfRangeException。
除了 -1 以外,不允许使用负的超时值。如果要使用 -1 以外的负整数来指定超时,系统将使用零(无超时)。如果指定的 TimeSpan 表示的是 -1 以外的负毫秒数,将引发 ArgumentOutOfRangeException。
 // This example shows a ReaderWriterLock protecting a shared
// This example shows a ReaderWriterLock protecting a shared // resource that is read concurrently and written exclusively
// resource that is read concurrently and written exclusively // by multiple threads.
// by multiple threads.
 // The complete code is located in the ReaderWriterLock
// The complete code is located in the ReaderWriterLock // class topic.
// class topic. using System;
using System; using System.Threading;
using System.Threading;
 public class Test
public class Test {
{ // Declaring the ReaderWriterLock at the class level
    // Declaring the ReaderWriterLock at the class level // makes it visible to all threads.
    // makes it visible to all threads. // 声明一个ReaderWriterLock,这样各个线程都可以访问它.
    // 声明一个ReaderWriterLock,这样各个线程都可以访问它. static ReaderWriterLock rwl = new ReaderWriterLock();
    static ReaderWriterLock rwl = new ReaderWriterLock(); // For this example, the shared resource protected by the
    // For this example, the shared resource protected by the // ReaderWriterLock is just an integer.
    // ReaderWriterLock is just an integer. static int resource = 0;
    static int resource = 0;
 const int numThreads = 26;
    const int numThreads = 26; static bool running = true;
    static bool running = true; static Random rnd = new Random();
    static Random rnd = new Random();
 // Statistics.
    // Statistics. static int readerTimeouts = 0;
    static int readerTimeouts = 0; static int writerTimeouts = 0;
    static int writerTimeouts = 0; static int reads = 0;
    static int reads = 0; static int writes = 0;
    static int writes = 0;
 public static void Main(string[] args)
    public static void Main(string[] args) {
    { // Start a series of threads. Each thread randomly
        // Start a series of threads. Each thread randomly // performs reads and writes on the shared resource.
        // performs reads and writes on the shared resource. // 开启几个线程.每个线程都随机的执行读写共享资源
        // 开启几个线程.每个线程都随机的执行读写共享资源 Thread[] t = new Thread[numThreads];
        Thread[] t = new Thread[numThreads]; for (int i = 0; i < numThreads; i++)
        for (int i = 0; i < numThreads; i++) {
        { t[i] = new Thread(new ThreadStart(ThreadProc));
            t[i] = new Thread(new ThreadStart(ThreadProc)); t[i].Name = new String(Convert.ToChar(i + 65), 1);
            t[i].Name = new String(Convert.ToChar(i + 65), 1); t[i].Start();
            t[i].Start(); if (i > 10)
            if (i > 10) Thread.Sleep(300);
                Thread.Sleep(300); }
        }
 // Tell the threads to shut down, then wait until they all
        // Tell the threads to shut down, then wait until they all // finish.
        // finish. // 通知线程关闭,等待直到他们都完成
        // 通知线程关闭,等待直到他们都完成 running = false;
        running = false; for (int i = 0; i < numThreads; i++)
        for (int i = 0; i < numThreads; i++) {
        { t[i].Join();
            t[i].Join(); }
        }
 // Display statistics.
        // Display statistics. Console.WriteLine("\r\n{0} reads, {1} writes, {2} reader time-outs, {3} writer time-outs.",
        Console.WriteLine("\r\n{0} reads, {1} writes, {2} reader time-outs, {3} writer time-outs.", reads, writes, readerTimeouts, writerTimeouts);
            reads, writes, readerTimeouts, writerTimeouts); Console.WriteLine("Press ENTER to exit.");
        Console.WriteLine("Press ENTER to exit."); Console.ReadLine();
        Console.ReadLine(); }
    }
 static void ThreadProc()
    static void ThreadProc() {
    { // As long as a thread runs, it randomly selects
        // As long as a thread runs, it randomly selects // various ways to read and write from the shared
        // various ways to read and write from the shared  // resource. Each of the methods demonstrates one
        // resource. Each of the methods demonstrates one  // or more features of ReaderWriterLock.
        // or more features of ReaderWriterLock. while (running)
        while (running) {
        { double action = rnd.NextDouble();
            double action = rnd.NextDouble(); if (action < .8)
            if (action < .8) ReadFromResource(10);
                ReadFromResource(10); else if (action < .81)
            else if (action < .81) ReleaseRestore(50);
                ReleaseRestore(50); else if (action < .90)
            else if (action < .90) UpgradeDowngrade(100);
                UpgradeDowngrade(100); else
            else WriteToResource(100);
                WriteToResource(100); }
        } }
    }
 // Shows how to request and release a reader lock, and
    // Shows how to request and release a reader lock, and // how to handle time-outs.
    // how to handle time-outs. // 显示如何请求和释放读锁,和如何操作过时。
    // 显示如何请求和释放读锁,和如何操作过时。 static void ReadFromResource(int timeOut)
    static void ReadFromResource(int timeOut) {
    { try
        try {
        { rwl.AcquireReaderLock(timeOut);
            rwl.AcquireReaderLock(timeOut); try
            try {
            { // It is safe for this thread to read from
                // It is safe for this thread to read from // the shared resource.
                // the shared resource. Display("reads resource value " + resource);
                Display("reads resource value " + resource); Interlocked.Increment(ref reads);
                Interlocked.Increment(ref reads); }
            } finally
            finally {
            { // Ensure that the lock is released.
                // Ensure that the lock is released. rwl.ReleaseReaderLock();
                rwl.ReleaseReaderLock(); }
            } }
        } catch (ApplicationException)
        catch (ApplicationException) {
        { // The reader lock request timed out.
            // The reader lock request timed out. Interlocked.Increment(ref readerTimeouts);
            Interlocked.Increment(ref readerTimeouts); }
        } }
    }
 // Shows how to request and release the writer lock, and
    // Shows how to request and release the writer lock, and // how to handle time-outs.
    // how to handle time-outs. static void WriteToResource(int timeOut)
    static void WriteToResource(int timeOut) {
    { try
        try {
        { rwl.AcquireWriterLock(timeOut);
            rwl.AcquireWriterLock(timeOut); try
            try {
            { // It is safe for this thread to read or write
                // It is safe for this thread to read or write // from the shared resource.
                // from the shared resource. resource = rnd.Next(500);
                resource = rnd.Next(500); Display("writes resource value " + resource);
                Display("writes resource value " + resource); Interlocked.Increment(ref writes);
                Interlocked.Increment(ref writes); }
            } finally
            finally {
            { // Ensure that the lock is released.
                // Ensure that the lock is released. rwl.ReleaseWriterLock();
                rwl.ReleaseWriterLock(); }
            } }
        } catch (ApplicationException)
        catch (ApplicationException) {
        { // The writer lock request timed out.
            // The writer lock request timed out. Interlocked.Increment(ref writerTimeouts);
            Interlocked.Increment(ref writerTimeouts); }
        } }
    }
 // Shows how to request a reader lock, upgrade the
    // Shows how to request a reader lock, upgrade the // reader lock to the writer lock, and downgrade to a
    // reader lock to the writer lock, and downgrade to a // reader lock again.
    // reader lock again. // 展示如何请求一个读锁,使读锁上升为写锁,然后又重新降为读锁。
    // 展示如何请求一个读锁,使读锁上升为写锁,然后又重新降为读锁。 static void UpgradeDowngrade(int timeOut)
    static void UpgradeDowngrade(int timeOut) {
    { try
        try {
        { rwl.AcquireReaderLock(timeOut);
            rwl.AcquireReaderLock(timeOut); try
            try {
            { // It is safe for this thread to read from
                // It is safe for this thread to read from // the shared resource.
                // the shared resource. Display("reads resource value " + resource);
                Display("reads resource value " + resource); Interlocked.Increment(ref reads);
                Interlocked.Increment(ref reads);
 // If it is necessary to write to the resource,
                // If it is necessary to write to the resource, // you must either release the reader lock and
                // you must either release the reader lock and  // then request the writer lock, or upgrade the
                // then request the writer lock, or upgrade the // reader lock. Note that upgrading the reader lock
                // reader lock. Note that upgrading the reader lock // puts the thread in the write queue, behind any
                // puts the thread in the write queue, behind any // other threads that might be waiting for the
                // other threads that might be waiting for the  // writer lock.
                // writer lock. try
                try {
                { LockCookie lc = rwl.UpgradeToWriterLock(timeOut);
                    LockCookie lc = rwl.UpgradeToWriterLock(timeOut); try
                    try {
                    { // It is safe for this thread to read or write
                        // It is safe for this thread to read or write // from the shared resource.
                        // from the shared resource. // 线程读写共享资源是安全的。
                        // 线程读写共享资源是安全的。 resource = rnd.Next(500);
                        resource = rnd.Next(500); Display("writes resource value " + resource);
                        Display("writes resource value " + resource); Interlocked.Increment(ref writes);
                        Interlocked.Increment(ref writes); }
                    } finally
                    finally {
                    { // Ensure that the lock is released.
                        // Ensure that the lock is released. rwl.DowngradeFromWriterLock(ref lc);
                        rwl.DowngradeFromWriterLock(ref lc); }
                    } }
                } catch (ApplicationException)
                catch (ApplicationException) {
                { // The upgrade request timed out.
                    // The upgrade request timed out. Interlocked.Increment(ref writerTimeouts);
                    Interlocked.Increment(ref writerTimeouts); }
                }
 // When the lock has been downgraded, it is
                // When the lock has been downgraded, it is  // still safe to read from the resource.
                // still safe to read from the resource. Display("reads resource value " + resource);
                Display("reads resource value " + resource); Interlocked.Increment(ref reads);
                Interlocked.Increment(ref reads); }
            } finally
            finally {
            { // Ensure that the lock is released.
                // Ensure that the lock is released. rwl.ReleaseReaderLock();
                rwl.ReleaseReaderLock(); }
            } }
        } catch (ApplicationException)
        catch (ApplicationException) {
        { // The reader lock request timed out.
            // The reader lock request timed out. Interlocked.Increment(ref readerTimeouts);
            Interlocked.Increment(ref readerTimeouts); }
        } }
    }
 // Shows how to release all locks and later restore
    // Shows how to release all locks and later restore // the lock state. Shows how to use sequence numbers
    // the lock state. Shows how to use sequence numbers // to determine whether another thread has obtained
    // to determine whether another thread has obtained // a writer lock since this thread last accessed the
    // a writer lock since this thread last accessed the // resource.
    // resource. // 展示如何释放所有的锁和恢复锁的状态.
    // 展示如何释放所有的锁和恢复锁的状态. // 展示利用顺序数字来决定另外一个线程是否获取读锁,当这个线程最后访问资源后.
    // 展示利用顺序数字来决定另外一个线程是否获取读锁,当这个线程最后访问资源后. static void ReleaseRestore(int timeOut)
    static void ReleaseRestore(int timeOut) {
    { int lastWriter;
        int lastWriter;
 try
        try {
        { rwl.AcquireReaderLock(timeOut);
            rwl.AcquireReaderLock(timeOut); try
            try {
            { // It is safe for this thread to read from
                // It is safe for this thread to read from // the shared resource. Cache the value. (You
                // the shared resource. Cache the value. (You // might do this if reading the resource is
                // might do this if reading the resource is // an expensive operation.)
                // an expensive operation.) int resourceValue = resource;
                int resourceValue = resource; Display("reads resource value " + resourceValue);
                Display("reads resource value " + resourceValue); Interlocked.Increment(ref reads);
                Interlocked.Increment(ref reads);
 // Save the current writer sequence number.
                // Save the current writer sequence number. lastWriter = rwl.WriterSeqNum;
                lastWriter = rwl.WriterSeqNum;
 // Release the lock, and save a cookie so the
                // Release the lock, and save a cookie so the // lock can be restored later.
                // lock can be restored later. LockCookie lc = rwl.ReleaseLock();
                LockCookie lc = rwl.ReleaseLock();
 // Wait for a random interval (up to a
                // Wait for a random interval (up to a  // quarter of a second), and then restore
                // quarter of a second), and then restore // the previous state of the lock. Note that
                // the previous state of the lock. Note that // there is no time-out on the Restore method.
                // there is no time-out on the Restore method. Thread.Sleep(rnd.Next(250));
                Thread.Sleep(rnd.Next(250)); rwl.RestoreLock(ref lc);
                rwl.RestoreLock(ref lc);
 // Check whether other threads obtained the
                // Check whether other threads obtained the // writer lock in the interval. If not, then
                // writer lock in the interval. If not, then // the cached value of the resource is still
                // the cached value of the resource is still // valid.
                // valid. if (rwl.AnyWritersSince(lastWriter))
                if (rwl.AnyWritersSince(lastWriter)) {
                { resourceValue = resource;
                    resourceValue = resource; Interlocked.Increment(ref reads);
                    Interlocked.Increment(ref reads); Display("resource has changed " + resourceValue);
                    Display("resource has changed " + resourceValue); }
                } else
                else {
                { Display("resource has not changed " + resourceValue);
                    Display("resource has not changed " + resourceValue); }
                } }
            } finally
            finally {
            { // Ensure that the lock is released.
                // Ensure that the lock is released. rwl.ReleaseReaderLock();
                rwl.ReleaseReaderLock(); }
            } }
        } catch (ApplicationException)
        catch (ApplicationException) {
        { // The reader lock request timed out.
            // The reader lock request timed out. Interlocked.Increment(ref readerTimeouts);
            Interlocked.Increment(ref readerTimeouts); }
        } }
    }
 // Helper method briefly displays the most recent
    // Helper method briefly displays the most recent // thread action. Comment out calls to Display to
    // thread action. Comment out calls to Display to  // get a better idea of throughput.
    // get a better idea of throughput. static void Display(string msg)
    static void Display(string msg) {
    { Console.Write("Thread {0} {1}.       \r", Thread.CurrentThread.Name, msg);
        Console.Write("Thread {0} {1}.       \r", Thread.CurrentThread.Name, msg); }
    } }
}

 当两个或更多线程需要同时访问一个共享资源时,系统需要使用同步机制来确保一次只有一个线程使用该资源。Mutex 是同步基元,它只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。
当两个或更多线程需要同时访问一个共享资源时,系统需要使用同步机制来确保一次只有一个线程使用该资源。Mutex 是同步基元,它只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。
 可以使用 WaitHandle.WaitOne 方法请求互斥体的所属权。拥有互斥体的线程可以在对 WaitOne 的重复调用中请求相同的互斥体而不会阻止其执行。但线程必须调用 ReleaseMutex 方法同样多的次数以释放互斥体的所属权。Mutex 类强制线程标识,因此互斥体只能由获得它的线程释放。相反,Semaphore 类不强制线程标识。
可以使用 WaitHandle.WaitOne 方法请求互斥体的所属权。拥有互斥体的线程可以在对 WaitOne 的重复调用中请求相同的互斥体而不会阻止其执行。但线程必须调用 ReleaseMutex 方法同样多的次数以释放互斥体的所属权。Mutex 类强制线程标识,因此互斥体只能由获得它的线程释放。相反,Semaphore 类不强制线程标识。 
 如果线程在拥有互斥体时终止,则称此互斥体被放弃。此互斥体被设置为终止状态,下一个等待的线程获得所属权。如果没有线程拥有互斥体,则互斥体状态为终止。从 .NET Framework 2.0 版开始,需要该互斥体的下一个线程将引发 AbandonedMutexException。在 .NET Framework 2.0 版之前,这样不会引发任何异常。
如果线程在拥有互斥体时终止,则称此互斥体被放弃。此互斥体被设置为终止状态,下一个等待的线程获得所属权。如果没有线程拥有互斥体,则互斥体状态为终止。从 .NET Framework 2.0 版开始,需要该互斥体的下一个线程将引发 AbandonedMutexException。在 .NET Framework 2.0 版之前,这样不会引发任何异常。
 警告
警告  出现遗弃的 Mutex 表明存在严重的编码错误。如果某个线程在未释放互斥体时便退出,受此互斥体保护的数据结构可能处于不一致的状态。如果此数据结构的完整性能得到验证,下一个请求此互斥体所属权的线程就可以处理此异常并继续。
出现遗弃的 Mutex 表明存在严重的编码错误。如果某个线程在未释放互斥体时便退出,受此互斥体保护的数据结构可能处于不一致的状态。如果此数据结构的完整性能得到验证,下一个请求此互斥体所属权的线程就可以处理此异常并继续。  
 
 互斥体有两种类型:局部互斥体和已命名的系统互斥体。如果使用接受名称的构造函数创建 Mutex 对象,则该对象与具有该名称的操作系统对象关联。已命名的系统互斥体在整个操作系统中都可见,可用于同步进程活动。您可以创建多个 Mutex 对象来表示同一个已命名的系统互斥体,也可以使用 OpenExisting 方法打开现有的已命名系统互斥体。
互斥体有两种类型:局部互斥体和已命名的系统互斥体。如果使用接受名称的构造函数创建 Mutex 对象,则该对象与具有该名称的操作系统对象关联。已命名的系统互斥体在整个操作系统中都可见,可用于同步进程活动。您可以创建多个 Mutex 对象来表示同一个已命名的系统互斥体,也可以使用 OpenExisting 方法打开现有的已命名系统互斥体。
 局部互斥体仅存在于您的进程内。您的进程中任何引用局部 Mutex 对象的线程都可以使用它。每个 Mutex 对象都是一个单独的局部互斥体。
局部互斥体仅存在于您的进程内。您的进程中任何引用局部 Mutex 对象的线程都可以使用它。每个 Mutex 对象都是一个单独的局部互斥体。
 /*=====================================================================
/*===================================================================== File:      Mutex.cs
  File:      Mutex.cs
 Summary:   Demonstrates how to wait for an object to go signalled
  Summary:   Demonstrates how to wait for an object to go signalled */
*/

 using System;
using System; using System.Threading;
using System.Threading;

 class Resource {
class Resource { Mutex m = new Mutex();
   Mutex m = new Mutex();
 public void Access(Int32 threadNum) {
   public void Access(Int32 threadNum) { m.WaitOne();
      m.WaitOne(); try {
      try { Console.WriteLine("Start Resource access (Thread={0})", threadNum);
         Console.WriteLine("Start Resource access (Thread={0})", threadNum); Thread.Sleep(500);
         Thread.Sleep(500); Console.WriteLine("Stop  Resource access (Thread={0})", threadNum);
         Console.WriteLine("Stop  Resource access (Thread={0})", threadNum); }
      } finally {
      finally { m.ReleaseMutex();
         m.ReleaseMutex(); }
      } }
   } }
}

 class App {
class App { static Int32 numAsyncOps = 5;
   static Int32 numAsyncOps = 5; static AutoResetEvent asyncOpsAreDone = new AutoResetEvent(false);
   static AutoResetEvent asyncOpsAreDone = new AutoResetEvent(false); static Resource res = new Resource();
   static Resource res = new Resource();
 public static void Main() {
   public static void Main() { for (Int32 threadNum = 0; threadNum < 5; threadNum++) {
      for (Int32 threadNum = 0; threadNum < 5; threadNum++) { ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateResource), threadNum);
         ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateResource), threadNum); }
      }
 asyncOpsAreDone.WaitOne();
      asyncOpsAreDone.WaitOne(); Console.WriteLine("All operations have completed.");
      Console.WriteLine("All operations have completed."); Console.ReadLine();
      Console.ReadLine(); }
   }

 // The callback method's signature MUST match that of a System.Threading.TimerCallback
   // The callback method's signature MUST match that of a System.Threading.TimerCallback  // delegate (it takes an Object parameter and returns void)
   // delegate (it takes an Object parameter and returns void) static void UpdateResource(Object state) {
   static void UpdateResource(Object state) { res.Access((Int32) state);
      res.Access((Int32) state); if (Interlocked.Decrement(ref numAsyncOps) == 0)
      if (Interlocked.Decrement(ref numAsyncOps) == 0) asyncOpsAreDone.Set();
         asyncOpsAreDone.Set(); }
   } }
}
毛毛的小窝
posted on 2007-05-16 11:03 mjgforever 阅读(1054) 评论(0) 收藏 举报
 
                    
                     
                    
                 
                    
                 
 
        

 
     
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号