c#自定义业务锁
我们有这样的使用场景,某个订单在修改信息的时候,其他人不能修改相关的信息,比如不能做支付,不能退单等等,那么我们可以根据单号进行加锁,多Monitor做了如下扩展
定义接口
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//// 文件名称:ILockExt.cs //// 创建日期:2018-06-07 10:44:39 // 功能描述:自定义锁接口 // using System; using System.Collections.Generic; using System.Linq; using System.Runtime.ConstrainedExecution; using System.Text; namespace Km.Utils.Helpers { /// <summary> /// 功能描述:自定义锁接口 ////// 创建日期:2018-06-07 10:41:47 ////// </summary> public interface ILockExt : IDisposable { /// <summary> /// 功能描述:在指定对象上获取排他锁。 ////// 创建日期:2018-06-07 10:25:29 ////// </summary> /// <param name="obj">在其上获取监视器锁的对象</param> void Enter(object obj); /// <summary> /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。 ////// 创建日期:2018-06-07 10:27:21 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为true</param> void Enter(object obj, ref bool lockTaken); /// <summary> /// 功能描述:释放指定对象上的排他锁 ////// 创建日期:2018-06-07 10:36:51 ////// </summary> /// <param name="obj">在其上释放锁的对象</param> [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] void Exit(object obj); /// <summary> /// 功能描述:通知等待队列中的线程锁定对象状态的更改。 ////// 创建日期:2018-06-07 10:37:15 ////// </summary> /// <param name="obj">线程正在等待的对象</param> void Pulse(object obj); /// <summary> /// 功能描述:通知所有的等待线程对象状态的更改。 ////// 创建日期:2018-06-07 10:37:40 ////// </summary> /// <param name="obj">发送脉冲的对象</param> void PulseAll(object obj); /// <summary> /// 功能描述:尝试获取指定对象的排他锁 ////// 创建日期:2018-06-07 10:37:55 ////// </summary> /// <param name="obj">在其上获取锁的对象。</param> /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns> bool TryEnter(object obj); /// <summary> /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。 ////// 创建日期:2018-06-07 10:38:11 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param> /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns> bool TryEnter(object obj, int millisecondsTimeout); /// <summary> /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。 ////// 创建日期:2018-06-07 10:38:34 ////// </summary> /// <param name="obj">obj</param> /// <param name="lockTaken">lockTaken</param> void TryEnter(object obj, ref bool lockTaken); /// <summary> /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。 ////// 创建日期:2018-06-07 10:39:28 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="timeout">System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param> /// <returns>如果当前线程在不阻止的情况下获取该锁,则为 true;否则为 false</returns> bool TryEnter(object obj, TimeSpan timeout); /// <summary> /// 功能描述:在指定的毫秒数中,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁 ////// 创建日期:2018-06-07 10:40:54 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param> /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param> void TryEnter(object obj, int millisecondsTimeout, ref bool lockTaken); /// <summary> /// 功能描述:在指定的一段时间内,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。 ////// 创建日期:2018-06-07 11:12:21 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="timeout">用于等待锁的时间。值为 -1 毫秒表示指定无限期等待</param> /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param> void TryEnter(object obj, TimeSpan timeout, ref bool lockTaken); /// <summary> /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。 ////// 创建日期:2018-06-07 11:12:45 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <returns> 如果调用由于调用方重新获取了指定对象的锁而返回,则为 true。如果未重新获取该锁,则此方法不会返回。</returns> bool Wait(object obj); /// <summary> /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。 ////// 创建日期:2018-06-07 11:13:13 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param> /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns> bool Wait(object obj, int millisecondsTimeout); /// <summary> /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。 ////// 创建日期:2018-06-07 11:13:35 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量。</param> /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns> bool Wait(object obj, TimeSpan timeout); /// <summary> /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。此方法还指定是否在等待之前退出上下文的同步域(如果处于同步上下文中的话)然后重新获取该同步域。 ////// 创建日期:2018-06-07 11:14:02 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param> /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param> /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns> bool Wait(object obj, int millisecondsTimeout, bool exitContext); /// <summary> /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。可以在等待之前退出同步上下文的同步域,随后重新获取该域。 ////// 创建日期:2018-06-07 11:14:34 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量</param> /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param> /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns> bool Wait(object obj, TimeSpan timeout, bool exitContext); /// <summary> /// 功能描述:在指定对象上获取排他锁 ////// 创建日期:2018-06-07 10:09:25 ////// </summary> /// <param name="obj">在其上获取监视器锁的对象</param> /// <returns>ILockExt对象</returns> ILockExt EnterLock(object obj); /// <summary> /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。 ////// 创建日期:2018-06-07 10:10:02 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。Note如果没有发生异常,则此方法的输出始终为true</param> /// <returns>ILockExt对象</returns> ILockExt EnterLock(object obj, ref bool lockTaken); /// <summary> /// 功能描述:尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。 ////// 创建日期:2018-06-07 10:17:29 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param> /// <returns>返回值</returns> ILockExt TryEnterLock(object obj, ref bool lockTaken); /// <summary> /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。 ////// 创建日期:2018-06-07 10:14:36 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param> /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param> /// <returns>ILockExt对象</returns> ILockExt TryEnterLock(object obj, int millisecondsTimeout, ref bool lockTaken); /// <summary> /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。 ////// 创建日期:2018-06-07 10:15:50 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="timeout"> System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param> /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param> /// <returns>ILockExt对象</returns> ILockExt TryEnterLock(object obj, TimeSpan timeout, ref bool lockTaken); } }
定义基类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace Km.Utils.Helpers { /// <summary> /// 功能描述:自定义锁 ////// 创建日期:2018-06-07 10:49:26 ////// </summary> public class LockExt : ILockExt { private static Dictionary<int, string> m_lstLocks = new Dictionary<int, string>(); /// <summary> /// 获取一个新实例 /// </summary> public static ILockExt Instance { get { return new LockExt(); } } /// <summary> /// 字符串锁类型格式化 by beck.huang 2018-06-07 11:00:25 /// </summary> public string LockFormate { get; set; } //锁对象 private int objLockKey; #region 构造函数 /// <summary> /// 功能描述:构造函数 ////// 创建日期:2018-06-07 10:49:46 ////// </summary> public LockExt() { } /// <summary> /// 功能描述:执行与释放或重置非托管资源相关的应用程序定义的任务。 ////// 创建日期:2018-06-07 10:49:18 ////// </summary> public void Dispose() { if (objLockKey != 0 && m_lstLocks.ContainsKey(objLockKey)) { Monitor.Pulse(m_lstLocks[objLockKey]); Monitor.Exit(m_lstLocks[objLockKey]); lock (m_lstLocks) { //如果可以尝试获得锁,则表示没有其他地方使用锁,则移除锁 if (Monitor.TryEnter(m_lstLocks[objLockKey], 0)) { Monitor.Exit(m_lstLocks[objLockKey]); m_lstLocks.Remove(objLockKey); } } } } #endregion /// <summary> /// 功能描述:设置锁 ////// 创建日期:2018-06-07 11:59:44 ////// </summary> /// <param name="obj">obj</param> private void SetLockObj(object obj) { if (obj is string) { if (string.IsNullOrEmpty(LockFormate) || LockFormate.IndexOf("{0}") < 0) { LockFormate = "{0}"; } objLockKey = string.Format(LockFormate, obj).GetHashCode(); } else { objLockKey = obj.GetHashCode(); } } /// <summary> /// 功能描述:在指定对象上获取排他锁。 ////// 创建日期:2018-06-07 10:25:29 ////// </summary> /// <param name="obj">在其上获取监视器锁的对象</param> public void Enter(object obj) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString()); } } Monitor.Enter(m_lstLocks[objLockKey]); } /// <summary> /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。 ////// 创建日期:2018-06-07 10:27:21 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为true</param> public void Enter(object obj, ref bool lockTaken) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString()); } } Monitor.Enter(m_lstLocks[objLockKey], ref lockTaken); } /// <summary> /// 功能描述:释放指定对象上的排他锁 ////// 创建日期:2018-06-07 10:36:51 ////// </summary> /// <param name="obj">在其上释放锁的对象</param> public void Exit(object obj) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { return; } } Monitor.Exit(m_lstLocks[objLockKey]); } /// <summary> /// 功能描述:通知等待队列中的线程锁定对象状态的更改。 ////// 创建日期:2018-06-07 10:37:15 ////// </summary> /// <param name="obj">线程正在等待的对象</param> public void Pulse(object obj) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { return; } } Monitor.Pulse(m_lstLocks[objLockKey]); } /// <summary> /// 功能描述:通知所有的等待线程对象状态的更改。 ////// 创建日期:2018-06-07 10:37:40 ////// </summary> /// <param name="obj">发送脉冲的对象</param> public void PulseAll(object obj) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { return; } } Monitor.PulseAll(m_lstLocks[objLockKey]); } /// <summary> /// 功能描述:尝试获取指定对象的排他锁 ////// 创建日期:2018-06-07 10:37:55 ////// </summary> /// <param name="obj">在其上获取锁的对象。</param> /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns> public bool TryEnter(object obj) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString()); } } bool bln = Monitor.TryEnter(m_lstLocks[objLockKey]); if (!bln) { lock (m_lstLocks) { m_lstLocks.Remove(objLockKey); } } return bln; } /// <summary> /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。 ////// 创建日期:2018-06-07 10:38:11 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param> /// <returns>如果当前线程获取该锁,则为 true;否则为 false。</returns> public bool TryEnter(object obj, int millisecondsTimeout) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString()); } } bool bln = Monitor.TryEnter(m_lstLocks[objLockKey], millisecondsTimeout); if (!bln) { lock (m_lstLocks) { m_lstLocks.Remove(objLockKey); } } return bln; } /// <summary> /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。 ////// 创建日期:2018-06-07 10:38:34 ////// </summary> /// <param name="obj">obj</param> /// <param name="lockTaken">lockTaken</param> public void TryEnter(object obj, ref bool lockTaken) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString()); } } Monitor.TryEnter(m_lstLocks[objLockKey], ref lockTaken); if (!lockTaken) { if (!lockTaken) { lock (m_lstLocks) { m_lstLocks.Remove(objLockKey); } } } } /// <summary> /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。 ////// 创建日期:2018-06-07 10:39:28 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="timeout">System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param> /// <returns>如果当前线程在不阻止的情况下获取该锁,则为 true;否则为 false</returns> public bool TryEnter(object obj, TimeSpan timeout) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString()); } } bool lockTaken = Monitor.TryEnter(m_lstLocks[objLockKey], timeout); if (!lockTaken) { lock (m_lstLocks) { m_lstLocks.Remove(objLockKey); } } return lockTaken; } /// <summary> /// 功能描述:在指定的毫秒数中,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁 ////// 创建日期:2018-06-07 10:40:54 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param> /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param> public void TryEnter(object obj, int millisecondsTimeout, ref bool lockTaken) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString()); } } Monitor.TryEnter(m_lstLocks[objLockKey], millisecondsTimeout, ref lockTaken); if (!lockTaken) { lock (m_lstLocks) { m_lstLocks.Remove(objLockKey); } } } /// <summary> /// 功能描述:在指定的一段时间内,尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。 ////// 创建日期:2018-06-07 11:12:21 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="timeout">用于等待锁的时间。值为 -1 毫秒表示指定无限期等待</param> /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param> public void TryEnter(object obj, TimeSpan timeout, ref bool lockTaken) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { m_lstLocks.Add(objLockKey, Guid.NewGuid().ToString()); } } Monitor.TryEnter(m_lstLocks[objLockKey], timeout, ref lockTaken); if (!lockTaken) { lock (m_lstLocks) { m_lstLocks.Remove(objLockKey); } } } /// <summary> /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。 ////// 创建日期:2018-06-07 11:12:45 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <returns> 如果调用由于调用方重新获取了指定对象的锁而返回,则为 true。如果未重新获取该锁,则此方法不会返回。</returns> public bool Wait(object obj) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { return false; } } return Monitor.Wait(m_lstLocks[objLockKey]); } /// <summary> /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。 ////// 创建日期:2018-06-07 11:13:13 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param> /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns> public bool Wait(object obj, int millisecondsTimeout) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { return false; } } return Monitor.Wait(m_lstLocks[objLockKey], millisecondsTimeout); } /// <summary> /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。 ////// 创建日期:2018-06-07 11:13:35 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量。</param> /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns> public bool Wait(object obj, TimeSpan timeout) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { return false; } } return Monitor.Wait(m_lstLocks[objLockKey], timeout); } /// <summary> /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。此方法还指定是否在等待之前退出上下文的同步域(如果处于同步上下文中的话)然后重新获取该同步域。 ////// 创建日期:2018-06-07 11:14:02 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="millisecondsTimeout">线程进入就绪队列之前等待的毫秒数</param> /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param> /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns> public bool Wait(object obj, int millisecondsTimeout, bool exitContext) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { return false; } } return Monitor.Wait(m_lstLocks[objLockKey], millisecondsTimeout, exitContext); } /// <summary> /// 功能描述:释放对象上的锁并阻止当前线程,直到它重新获取该锁。如果指定的超时间隔已过,则线程进入就绪队列。可以在等待之前退出同步上下文的同步域,随后重新获取该域。 ////// 创建日期:2018-06-07 11:14:34 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="timeout">System.TimeSpan,表示线程进入就绪队列之前等待的时间量</param> /// <param name="exitContext"> 如果在等待前退出并重新获取上下文的同步域(如果在同步上下文中),则为 true;否则为 false。</param> /// <returns>如果在指定的时间过期之前重新获取该锁,则为 true;如果在指定的时间过期之后重新获取该锁,则为 false。此方法只有在重新获取该锁后才会返回。</returns> public bool Wait(object obj, TimeSpan timeout, bool exitContext) { SetLockObj(obj); lock (m_lstLocks) { if (!m_lstLocks.ContainsKey(objLockKey)) { return false; } } return Monitor.Wait(m_lstLocks[objLockKey], timeout, exitContext); } /// <summary> /// 功能描述:在指定对象上获取排他锁 ////// 创建日期:2018-06-07 10:09:25 ////// </summary> /// <param name="obj">在其上获取监视器锁的对象</param> /// <returns>ILockExt对象</returns> public ILockExt EnterLock(object obj) { Enter(obj); return this; } /// <summary> /// 功能描述:获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。 ////// 创建日期:2018-06-07 10:10:02 ////// </summary> /// <param name="obj">要在其上等待的对象</param> /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。Note如果没有发生异常,则此方法的输出始终为true</param> /// <returns>ILockExt对象</returns> public ILockExt EnterLock(object obj, ref bool lockTaken) { Enter(obj, ref lockTaken); return this; } /// <summary> /// 功能描述:尝试获取指定对象上的排他锁,并自动设置一个值,指示是否获取了该锁。 ////// 创建日期:2018-06-07 10:17:29 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="lockTaken">尝试获取锁的结果,通过引用传递。输入必须为 false。如果已获取锁,则输出为 true;否则输出为 false。即使在尝试获取锁的过程中发生异常,也会设置输出。</param> /// <returns>返回值</returns> public ILockExt TryEnterLock(object obj, ref bool lockTaken) { TryEnter(obj, ref lockTaken); return this; } /// <summary> /// 功能描述:在指定的毫秒数内尝试获取指定对象上的排他锁。 ////// 创建日期:2018-06-07 10:14:36 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="millisecondsTimeout">等待锁所需的毫秒数</param> /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param> /// <returns>ILockExt对象</returns> public ILockExt TryEnterLock(object obj, int millisecondsTimeout, ref bool lockTaken) { TryEnter(obj, millisecondsTimeout, ref lockTaken); return this; } /// <summary> /// 功能描述:在指定的时间量内尝试获取指定对象上的排他锁。 ////// 创建日期:2018-06-07 10:15:50 ////// </summary> /// <param name="obj">在其上获取锁的对象</param> /// <param name="timeout"> System.TimeSpan,表示等待锁所需的时间量。值为 -1 毫秒表示指定无限期等待。</param> /// <param name="lockTaken">如果当前线程获取该锁,则为 true;否则为 false</param> /// <returns>ILockExt对象</returns> public ILockExt TryEnterLock(object obj, TimeSpan timeout, ref bool lockTaken) { TryEnter(obj, timeout, ref lockTaken); return this; } } }
定义业务锁
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//// 文件名称:LockExtList.cs //// 创建日期:2018-06-07 11:46:47 // 功能描述:锁列表 // using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Km.Utils.Helpers { /* 说明 * 注: * 编写锁步骤说明: * 1、编写对应类继承LockExt * 2、编写属性如下 * public static ILockExt Instance { get { LockOfTable l = new LockOfTable(); l.LockFormate = "BillTableLock({0})"; return l; } } * * 使用锁说明: * 1、快捷使用如下 * //排队获得锁 * using (LockOfTable.Instance.EnterLock("台位号")) * { * //你的操作 * } * //尝试获得锁 * bool blnLockTaken = false; * using (LockOfTable.Instance.TryEnterLock("台位号", ref blnLockTaken)) * { * if (!blnLockTaken) * { * //台位已被锁定 * return; * } * //你的操作 * } * * 2、普通使用如下(更多的控制,但是要手动调用Exit进行释放锁) * LockOfTable tableLock = LockOfTable.Instance; * tableLock.Enter("台位号"); * tableLock.Pulse("台位号"); * tableLock.Wait("台位号"); * tableLock.Exit("台位号"); * ... */ #region 台位锁 /// <summary> /// 功能描述:台位锁 ////// 创建日期:2018-06-07 11:30:45 ////// </summary> public class LockOfTable : LockExt { public static ILockExt Instance { get { LockOfTable l = new LockOfTable(); l.LockFormate = "BillTableLock({0})"; return l; } } } #endregion #region 出品单锁 /// <summary> /// 功能描述:出品单锁 ////// 创建日期:2018-06-07 11:35:56 ////// </summary> public class LockOfBill0 : LockExt { public static ILockExt Instance { get { LockOfTable l = new LockOfTable(); l.LockFormate = "Bill0Lock({0})"; return l; } } } #endregion }
使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using (LockOfTable.Instance.EnterLock("123456")) { Console.WriteLine("enter:" + i); Console.WriteLine(i); Thread.Sleep(1000); }
作者:冰封一夏
出处:http://www.cnblogs.com/bfyx/
HZHControls官网:http://www.hzhcontrols.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,
且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git