基于TPL异步编程的同步和互斥的类库

在多线程编程中,我们除了并发外,往往还需要各线程直接进行互斥和同步等操作,.Net Framework在System.Threading中提供了不少库供我们实现这些功能,如:Mutex,ReaderWriterLock,ManualResetEvent,AutoResetEvent,Barrier等。在基于TPL的异步编程中,我们往往也需要这样的类库来实现异步的同步和互斥功能,但.Net Framework没有为我们提供这些类库,往往得自己实现,比较麻烦。今天在MSDN Blog上发现了一个大牛的实现,非常全面,这里强烈推荐一下。 

AsyncManualResetEvent

ExpandedBlockStart.gif View Code
     // http://blogs.msdn.com/b/pfxteam/archive/2012/02/11/10266920.aspx
     public  class AsyncManualResetEvent
    {
         private  volatile TaskCompletionSource< bool> m_tcs =  new TaskCompletionSource< bool>();

         public Task WaitAsync() {  return m_tcs.Task; }

         public  void Set() { m_tcs.TrySetResult( true); }

         public  void Reset()
        {
             lock (m_tcs)
            {
                 if (!m_tcs.Task.IsCompleted)
                {
                    Task.Factory.StartNew(s => ((TaskCompletionSource< bool>)s).TrySetResult( true), m_tcs).Wait();
                }
                m_tcs =  new TaskCompletionSource< bool>();
            }
            
        }
    }

 

AsyncAutoResetEvent

ExpandedBlockStart.gif View Code
     // http://blogs.msdn.com/b/pfxteam/archive/2012/02/11/10266923.aspx
     public  class AsyncAutoResetEvent
    {
         private  readonly  static Task s_completed = Task.FromResult( true);
         private  readonly Queue<TaskCompletionSource< bool>> m_waits =  new Queue<TaskCompletionSource< bool>>();
         private  bool m_signaled;

         public Task WaitAsync()
        {
             lock (m_waits)
            {
                 if (m_signaled)
                {
                    m_signaled =  false;
                     return s_completed;
                }
                 else
                {
                     var tcs =  new TaskCompletionSource< bool>();
                    m_waits.Enqueue(tcs);
                     return tcs.Task;
                }
            } 
        }

         public  void Set()
        {
            TaskCompletionSource< bool> toRelease =  null;
             lock (m_waits)
            {
                 if (m_waits.Count >  0)
                    toRelease = m_waits.Dequeue();
                 else  if (!m_signaled)
                    m_signaled =  true;
            }
             if (toRelease !=  null)
                toRelease.SetResult( true); 
        }
    }

 

AsyncCountdownEvent

ExpandedBlockStart.gif View Code
     // http://blogs.msdn.com/b/pfxteam/archive/2012/02/11/10266930.aspx
     public  class AsyncCountdownEvent
    {
         private  readonly AsyncManualResetEvent m_amre =  new AsyncManualResetEvent();
         private  int m_count;

         public AsyncCountdownEvent( int initialCount)
        {
             if (initialCount <=  0throw  new ArgumentOutOfRangeException( " initialCount ");
            m_count = initialCount; 
        }
        
         public Task WaitAsync() {  return m_amre.WaitAsync(); }
        
         public  void Signal()
        {
             if (m_count <=  0)
                 throw  new InvalidOperationException();

             int newCount = Interlocked.Decrement( ref m_count);
             if (newCount ==  0)
                m_amre.Set();
             else  if (newCount <  0)
                 throw  new InvalidOperationException();
        }

         public Task SignalAndWait()
        {
            Signal();
             return WaitAsync();
        }
    }

 

AsyncBarrier

ExpandedBlockStart.gif View Code
     // http://blogs.msdn.com/b/pfxteam/archive/2012/02/11/10266932.aspx
     public  class AsyncBarrier
    {
         private  readonly  int m_participantCount;
         private  int m_remainingParticipants;
         private ConcurrentStack<TaskCompletionSource< bool>> m_waiters;

         public AsyncBarrier( int participantCount)
        {
             if (participantCount <=  0throw  new ArgumentOutOfRangeException( " participantCount ");
            m_remainingParticipants = m_participantCount = participantCount;
            m_waiters =  new ConcurrentStack<TaskCompletionSource< bool>>();
        }

         public Task SignalAndWait()
        {
             var tcs =  new TaskCompletionSource< bool>();
            m_waiters.Push(tcs);
             if (Interlocked.Decrement( ref m_remainingParticipants) ==  0)
            {
                m_remainingParticipants = m_participantCount;
                 var waiters = m_waiters;
                m_waiters =  new ConcurrentStack<TaskCompletionSource< bool>>();
                Parallel.ForEach(waiters, w => w.SetResult( true));
            }
             return tcs.Task;
        }
    }

 

 AsyncSemaphore 

ExpandedBlockStart.gif View Code
     // http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266983.aspx
     public  class AsyncSemaphore
    {
         private  readonly  static Task s_completed = Task.FromResult( true);
         private  readonly Queue<TaskCompletionSource< bool>> m_waiters =  new Queue<TaskCompletionSource< bool>>();
         private  int m_currentCount;

         public AsyncSemaphore( int initialCount)
        {
             if (initialCount <  0throw  new ArgumentOutOfRangeException( " initialCount ");
            m_currentCount = initialCount;
        } 

         public Task WaitAsync()
        {
             lock (m_waiters)
            {
                 if (m_currentCount >  0)
                {
                    --m_currentCount;
                     return s_completed;
                }
                 else
                {
                     var waiter =  new TaskCompletionSource< bool>();
                    m_waiters.Enqueue(waiter);
                     return waiter.Task;
                }
            }
        }

         public  void Release()
        {
            TaskCompletionSource< bool> toRelease =  null;
             lock (m_waiters)
            {
                 if (m_waiters.Count >  0)
                    toRelease = m_waiters.Dequeue();
                 else
                    ++m_currentCount;
            }
             if (toRelease !=  null)
                toRelease.SetResult( true);
        }
    }

 

  AsyncLock

ExpandedBlockStart.gif View Code
     // http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266988.aspx
     public  class AsyncLock
    {
         private  readonly AsyncSemaphore m_semaphore;
         private  readonly Task<Releaser> m_releaser;

         public AsyncLock()
        {
            m_semaphore =  new AsyncSemaphore( 1);
            m_releaser = Task.FromResult( new Releaser( this));
        }

         public Task<Releaser> LockAsync()
        {
             var wait = m_semaphore.WaitAsync();
             return wait.IsCompleted ?
                m_releaser :
                wait.ContinueWith((_, state) =>  new Releaser((AsyncLock)state),
                     this, CancellationToken.None,
                    TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
        }

         public  struct Releaser : IDisposable
        {
             private  readonly AsyncLock m_toRelease;

             internal Releaser(AsyncLock toRelease) { m_toRelease = toRelease; }

             public  void Dispose()
            {
                 if (m_toRelease !=  null)
                    m_toRelease.m_semaphore.Release();
            }
        }
    }

 

 AsyncReaderWriterLock

ExpandedBlockStart.gif View Code
     // http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10267069.aspx
     public  class AsyncReaderWriterLock
    {
         private  readonly Task<Releaser> m_readerReleaser;
         private  readonly Task<Releaser> m_writerReleaser;

         private  readonly Queue<TaskCompletionSource<Releaser>> m_waitingWriters =  new Queue<TaskCompletionSource<Releaser>>();
         private TaskCompletionSource<Releaser> m_waitingReader =  new TaskCompletionSource<Releaser>();
         private  int m_readersWaiting;
         private  int m_status;

         public AsyncReaderWriterLock()
        {
            m_readerReleaser = Task.FromResult( new Releaser( thisfalse));
            m_writerReleaser = Task.FromResult( new Releaser( thistrue));
        }

         public Task<Releaser> ReaderLockAsync()
        {
             lock (m_waitingWriters)
            {
                 if (m_status >=  0 && m_waitingWriters.Count ==  0)
                {
                    ++m_status;
                     return m_readerReleaser;
                }
                 else
                {
                    ++m_readersWaiting;
                     return m_waitingReader.Task;
                }
            }
        }


         public Task<Releaser> WriterLockAsync()
        {
             lock (m_waitingWriters)
            {
                 if (m_status ==  0)
                {
                    m_status = - 1;
                     return m_writerReleaser;
                }
                 else
                {
                     var waiter =  new TaskCompletionSource<Releaser>();
                    m_waitingWriters.Enqueue(waiter);
                     return waiter.Task;
                }
            }
        }

         private  void ReaderRelease()
        {
            TaskCompletionSource<Releaser> toWake =  null;

             lock (m_waitingWriters)
            {
                --m_status;
                 if (m_status ==  0 && m_waitingWriters.Count >  0)
                {
                    m_status = - 1;
                    toWake = m_waitingWriters.Dequeue();
                }
            }

             if (toWake !=  null)
                toWake.SetResult( new Releaser( thistrue));
        }

         private  void WriterRelease()
        {
            TaskCompletionSource<Releaser> toWake =  null;
             bool toWakeIsWriter =  false;

             lock (m_waitingWriters)
            {
                 if (m_waitingWriters.Count >  0)
                {
                    toWake = m_waitingWriters.Dequeue();
                    toWakeIsWriter =  true;
                }
                 else  if (m_readersWaiting >  0)
                {
                    toWake = m_waitingReader;
                    m_status = m_readersWaiting;
                    m_readersWaiting =  0;
                    m_waitingReader =  new TaskCompletionSource<Releaser>();
                }
                 else m_status =  0;
            }

             if (toWake !=  null)
                toWake.SetResult( new Releaser( this, toWakeIsWriter));
        }

         public  struct Releaser : IDisposable
        {
             private  readonly AsyncReaderWriterLock m_toRelease;
             private  readonly  bool m_writer;

             internal Releaser(AsyncReaderWriterLock toRelease,  bool writer)
            {
                m_toRelease = toRelease;
                m_writer = writer;
            }

             public  void Dispose()
            {
                 if (m_toRelease !=  null)
                {
                     if (m_writer) m_toRelease.WriterRelease();
                     else m_toRelease.ReaderRelease();
                }
            }
        }
    }

 

转载于:https://www.cnblogs.com/TianFang/archive/2012/06/24/2559972.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值