C# 防止来自用户的并发控制器请求

C# 防止来自用户的并发控制器请求,c#,asp.net-mvc,model-view-controller,C#,Asp.net Mvc,Model View Controller,我的ASP.NETMVC项目中有一个控制器操作,不允许同一用户同时执行。 当用户提交请求1且请求1仍在运行时,应拒绝所有其他请求。此逻辑必须基于用户 我写了一些代码,我认为它可以工作 由于我在localhost上的测试有问题,而且它是我网站的敏感部分,如果您能查看代码并给我一些反馈,我将不胜感激 使现代化 我将下面的代码发布到产品中,有一次我遇到了一个用户创建了锁但没有解锁的情况。我不知道问题出在哪里 控制器 锁库 我希望只有当用户ID在锁Repo中时,请求才会被阻止。其他用户不应受到影响我认为

我的ASP.NETMVC项目中有一个控制器操作,不允许同一用户同时执行。 当用户提交请求1且请求1仍在运行时,应拒绝所有其他请求。此逻辑必须基于用户

我写了一些代码,我认为它可以工作

由于我在localhost上的测试有问题,而且它是我网站的敏感部分,如果您能查看代码并给我一些反馈,我将不胜感激

使现代化 我将下面的代码发布到产品中,有一次我遇到了一个用户创建了锁但没有解锁的情况。我不知道问题出在哪里

控制器 锁库
我希望只有当用户ID在锁Repo中时,请求才会被阻止。其他用户不应受到影响

我认为这不会一直奏效。如果两个操作请求同时调用HasLock方法呢?在执行代码行UserLocks.AdduserId;之前,这两个请求顺序地将变量hasLock设置为false;。 在这种情况下,您可能需要在HasLock方法中使用lock:

private static object _lockObj = new object();
public static bool HasLock(int userId)
{
   lock(_lockObj)    
   {
     var i = userId;
     var hasLock = UserLocks.TryPeek(out i);
     if (hasLock)
         return true;
     UserLocks.Add(userId);
     return false;
   }
}

说得好。我还应该在RemoveLock方法中添加一个锁,对吗?当TryTakeout userId失败时,用户永远不能再次调用操作。我不认为您需要在Remove方法中添加锁,因为如果锁定HasLock方法,则只有一个操作请求将通过,并且只有该请求将调用RemoveLock方法,换句话说,没有并发请求会调用Remove方法。不幸的是,一个用户有一个活动锁长达数小时,但没有解锁。我真的很困惑这怎么会发生。在没有例外的情况下,我会在归还物品之前移除锁扣中的锁。应明确达到解锁方法。代码与我最初的帖子中的代码相同,加上你建议的锁,这将一直有效,直到你的应用程序在冗余服务器(如服务器场)上运行。您可能需要使用事务在数据库中设置您的标志以缓解种族冲突。我已经实现了@Abdullah Dibas comment的建议。
public static class TransactionLockRepository
    {
        private static readonly ConcurrentBag<int> UserLocks = new ConcurrentBag<int>();
        private static readonly object _lockInsert = new object();
        private static readonly object _lockRemove = new object();

        public static bool HasLock(int userId)
        {
            lock (_lockInsert)
            {
                var i = userId;
                var hasLock = UserLocks.TryPeek(out i);
                if (hasLock)
                    return true;
                UserLocks.Add(userId);
                return false;
            }
        }

        public static bool RemoveLock(int userId)
        {
            lock (_lockRemove)
            {
                var i = userId;
                UserLocks.TryTake(out i);
                return i == userId;
            }
        }
    }
private static object _lockObj = new object();
public static bool HasLock(int userId)
{
   lock(_lockObj)    
   {
     var i = userId;
     var hasLock = UserLocks.TryPeek(out i);
     if (hasLock)
         return true;
     UserLocks.Add(userId);
     return false;
   }
}