async await 模式下的lock逻辑

原生的lock作用域中,不能使用async,await关键词。

但高性能程序中lock逻辑大量存在,这里使用dispose接口支持的using逻辑,实现一个替代的lock逻辑:

 

public class NameTaskLock
  {
    static NameTaskLock m_only = new NameTaskLock();
    public static NameTaskLock Current { get { return m_only; } }
    public class NameLock : IDisposable
    {
      public string Key { get; private set; }

      internal void ResetKey(string name)
      {
        this.Key = name;
      }
      
      public NameLock(string ask)
      {
        Key = ask;
      }
      public bool isReleased()
      {
        return string.IsNullOrEmpty(Key);
      }
      public void Dispose()
      {
        Key = null;
      }
    }

    public readonly static int MaxWaitSecond = 10;//最大等待时间。超过该时间,会抛出异常。
    public readonly static int MaxLockInMemery = 10000;//locked中最大的存储个数,超过该个数,会清理已销毁的NameLock项。

    Dictionary<string, NameLock> locked = new Dictionary<string, NameLock>();

    NameLock SetLock(string name)
    {//为当前
      lock (locked)
      {
        if (locked.ContainsKey(name))
        {
          var rt = locked[name];
          if (rt.isReleased())
          {
            rt.ResetKey(name);
            return rt;
          }
          else
            return null;
        }
        else
        {
          NameLock rt = new NameLock(name);
          locked[name] = rt;
          return rt;
        }
      }
    }
    void ClearLock()
    {
      lock (locked)
      {
        var keys = locked.Keys.ToList();
        foreach(var key in keys)
        {
          var theV = locked[key];
          if (theV.isReleased())
            locked.Remove(key);
        }
      }
    }

    public async Task<NameLock> GetLock(string name,int Second = -1)
    {
      if (locked.Count >= MaxLockInMemery)
        ClearLock();
      if (Second < 1)
        Second = MaxWaitSecond;

      DateTime enterTime = DateTime.Now;
      while (true)
      {
        var rt = SetLock(name);
        if (rt != null)
          return rt;
        else if ((DateTime.Now- enterTime).TotalSeconds > Second)
          throw new Exception("NameTaskLock尝试超时,请检查使用名为:" + name + "的NameTaskLock资源使用逻辑。资源使用方未在"+ Second + "秒内结束任务。");
        else
          await Task.Delay(100);
      }
    }
  }

 

使用方法:

  using(var LKobj = await SVR.NameTaskLock.Current.GetLock("My Test Key Info"))
   {
        System.Threading.Thread.Sleep(1000);
        Console.WriteLine(DateTime.Now.ToUniversalTime());
    }

在using区间内相同名称的任务会互斥。 代价是每100毫秒检查一次其他任务是否完成。

问题:

   1:如果使用 using(var LKobj = SVR.NameTaskLock.Current.GetLock("My Test Key Info")) 编译不会报错。 但如果发生互斥,将会有异常发生。

   2:不能嵌套! 嵌套使用必然会发生超时异常。

   

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值