zoukankan      html  css  js  c++  java
  • C# 异步锁【转】

    原文:http://www.yalongyang.com/2013/01/c-sharp-await-lock/

    在C#中,普通用锁很简单

        object m_lock = new object();
        lock(m_lock)
        {
            ......
        }

    其中 ...... 表示互斥的代码。
    这样就可以保证同时仅会有一个地方在执行这段互斥代码。

    然而如果互斥代码中由await调用,上面的方式就行不通了,由于普通的lock代码段中无法存在await调用。

    但是在实际使用中,经常遇见需要保护互斥的await情况,
    比如用 await FileIO.WriteTextAsync() 的调用写文件,需要保证同时仅有一个地方在调用此段代码,不然就会出现互斥错误。

    以下两篇文章很好的说明了如何实现对await调用互斥的处理。

    可以总结为以下代码

        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 < 0) throw 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);
            }
        }
    
        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();
                } 
            }
        }

    调用时仅需要:

        readonly AsyncLock m_lock = new AsyncLock(); 
        using (var releaser = await m_lock.LockAsync())
        {
            await FileIO.WriteTextAsync(configureFile, jsonString);
        }
  • 相关阅读:
    第二十八课:focusin与focusout,submit,oninput事件的修复
    第二十七课:滚轮事件,mouseenter与mouseleave事件的修复
    anaconda
    matlab 假设检验
    keras 中如何自定义损失函数
    如何理解 卷积 和pooling
    交叉熵代价函数(作用及公式推导)
    深度学习
    中文 停用词 词典
    英文 停用词 词典
  • 原文地址:https://www.cnblogs.com/walkerwang/p/3690768.html
Copyright © 2011-2022 走看看