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