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调用互斥的处理。
- Building Async Coordination Primitives, Part 5: AsyncSemaphore
- Building Async Coordination Primitives, Part 6: AsyncLock
可以总结为以下代码
- 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 < ) throw new ArgumentOutOfRangeException("initialCount");
- m_currentCount = initialCount;
- }
- public Task WaitAsync()
- {
- lock (m_waiters)
- {
- if (m_currentCount > )
- {
- --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 > )
- 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();
- 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);
- }
C# 异步锁【转】的更多相关文章
- 使用Nito.AsyncEx实现异步锁(转)
转载地址:http://www.cnblogs.com/1zhk/p/5269279.html Lock是常用的同步锁,但是我们无法在Lock的内部实现异步调用,比如我们无法使用await. 以下面的 ...
- 使用Nito.AsyncEx实现异步锁
Lock是常用的同步锁,但是我们无法在Lock的内部实现异步调用,比如我们无法使用await. 以下面的代码为例,当你在lock内部使用await时,VS会报错提醒. 最简单的解决办法就是使用第三方的 ...
- C# 异步锁 await async锁,lock,Monitor,SemaphoreSlim
异步方法内无法使用Monitor 和lock 所以只能用System.Threading.SemaphoreSlim了 //Semaphore (int initialCount, int maxim ...
- C# 异步锁
参考网址: https://www.cnblogs.com/Alicia-meng/p/13330640.html 使用SemaphoreSlim 实现 当多个任务或线程并行运行时,难以避免的对某些有 ...
- C#异步编程(五)异步的同步构造
异步的同步构造 任何使用了内核模式的线程同步构造,我都不是特别喜欢.因为所有这些基元都会阻塞一个线程的运行.创建线程的代价很大.创建了不用,这于情于理说不通. 创建了reader-writer锁的情况 ...
- C# 并发编程 (异步编程与多线程)
并发:同时做多件事情 多线程:并发的一种形式,它采用多个线程来执行程序. 并行处理:把正在执行的大量的任务分割成小块,分配给多个同时运行的线程.并行处理是多线程的一种,而多线程是并发的一种. 异步编程 ...
- zk客户端及锁的使用
1.生成zk客户端对象 private CuratorFramework buildClient() { logger.info("zookeeper registry center ini ...
- 单元测试NUnit,mock组件NSubstitute,信号量SemaphoreSlim,异步lock等例子
public class LockTest { private IDatabase _database; private readonly Random _random = new Random(); ...
- 【Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之RAC 工作原理和相关组件(三)
RAC 工作原理和相关组件(三) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总.然后形成体 ...
随机推荐
- JAVA-JSP内置对象之session对象设置并获得session生命周期
相关资料:<21天学通Java Web开发> session对象设置并获得session生命周期1.通过session对象的setMaxInactiveInterval()方法可以设置se ...
- 2. AutoEncoder在NLP中的应用
1. AutoEncoder介绍 2. Applications of AutoEncoder in NLP 3. Recursive Autoencoder(递归自动编码器) 4. Stacked ...
- 收藏mac重装php环境
参考网址: 全新安装Mac OSX 开发者环境 同时使用homebrew搭建 PHP,Nginx ,MySQL,Redis,Memcache ... ... (LNMP开发环境)
- Selenium (3) —— Selenium IDE + Firefox录制登录脚本(101 Tutorial)
Selenium (3) -- Selenium IDE + Firefox录制登录脚本(101 Tutorial) selenium IDE版本: 2.9.1 firefox版本: 39.0.3 参 ...
- hbase源码系列(六)HMaster启动过程
这一章是server端开始的第一章,有兴趣的朋友先去看一下hbase的架构图,我专门从网上弄下来的. 按照HMaster的run方法的注释,我们可以了解到它的启动过程会去做以下的动作. * <l ...
- 【C】——信号量 互斥锁 条件变量的区别
信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在哪里).而互斥锁是用在多线程多任务互斥的,一个线程占用了某 ...
- python转义符的使用
写了几行代码不能用.========有个需要的注意的就是在pycharm中看见蓝色字体要注意了一定是关键字什么,这个以后要注意. import os # g = os.walk("D:\aa ...
- -Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable and mvn script match.
在执行[maven clean]的时候报错,错误信息如下: -Dmaven.multiModuleProjectDirectory system property is not set. Check ...
- AD集成库元件简写中英文对照表
序号 英文简写 元件英文名 元件中文名 1 Res semi Semiconductor Resistor 半导体电阻 2 Cap semi Semiconductor Capacitor 半导体电容 ...
- 微信小程序——引用阿里云字体
阿里图标官网:http://www.iconfont.cn 使用阿里云图标大致的方法就是:选中你的图标——保存至你的项目——下载你的图标项目——在项目中引用字体文件. 具体方法可以参考:引用阿里云矢量 ...