ASP.. NET MVC 4:一次只允许一个请求



. NET MVC应用程序,我想按顺序处理所有请求;任何动作/控制器代码都不应该与其他代码同时执行。如果两个请求同时进入,它应该先运行第一个请求,然后在第一个请求完成后运行第二个请求。

除了使用全局锁变量之外,还有更好的方法吗?

编辑:该应用程序更像是一个通过web执行web服务调用和清理数据库的批处理/服务。站点中的不同url导致不同的批处理操作。这不是一个面向最终用户的网站。因此,我需要这样做,以便一次只执行一个对URL的请求(这将执行一些批处理操作),否则,如果批处理操作的代码与自身或其他批处理操作并发运行,则批处理操作可能会损坏。事实上,如果另一个请求在当前正在执行时出现,那么它根本不应该运行,即使在前一个请求完成之后;它应该只给出一个错误信息。

我想知道是否有一种方法在IIS中而不是代码中做到这一点。如果我有一个全局锁变量,它会使代码更加复杂,并且我可能会在锁变量被设置为true但永远不能被设置为false的情况下运行死锁。

编辑:实施方案示例代码

[HttpPost]
public ActionResult Batch1()
{
    //Config.Lock is a global static boolean variable
    if(Config.Lock) { Response.Write("Error: another batch process is running"); return View(); }
    Config.Lock = true; 
    //Run some batch calls and web services (this code cannot be interleaved with ExecuteBatchCode2() or itself)
    ExecuteBatchCode();
    Config.Lock = false;
    return View();
}
[HttpPost]
public ActionResult Batch2()
{
    if(Config.Lock) { Response.Write("Error: another batch process is running"); return View(); }
    Config.Lock = true;
    //Run some batch calls and web services (this code cannot be interleaved with ExecuteBatchCode1() or itself)
    ExecuteBatchCode2();
    Config.Lock = false;
    return View();
}

我需要担心的情况下,代码没有达到配置。Lock = false,导致Config。Lock = true永远,导致不再服务请求?

你可以写一个属性:

public class ExclusiveActionAttribute : ActionFilterAttribute
{
    private static int isExecuting = 0;
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (Interlocked.CompareExchange(ref isExecuting, 1, 0) == 0)
        {
            base.OnActionExecuting(filterContext);   
            return; 
        }
        filterContext.Result = 
            new HttpStatusCodeResult(HttpStatusCode.ServiceUnavailable);
    }
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        base.OnResultExecuted(filterContext);
        Interlocked.Exchange(ref isExecuting, 0);
    }
}

然后在你想控制的控制器/方法上使用它:

[ExclusiveAction] //either here, for every action in the controller
public class MyController : Controller
{
    [ExclusiveAction] //or here for specific methods
    public ActionResult DoTheThing()
    {
        //foo
        return SomeActionResult();
    }
}

你要尽可能地接受请求,人们不喜欢在浏览器前等待。但是在之后的,在服务端,您可以将它们推入(例如)Queue<T>并按顺序处理它们。

总之:

  • 异步接收
  • 进程,在服务器上,按顺序

上面的代码不工作可能是因为当请求1正在运行并发送请求2时,应用程序返回服务不可用,这很好,但如果请求1没有完成并再次发送请求2到应用程序,应用程序同时运行两个请求。我检查代码并修改它。

   [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class ExclusiveActionAttribute : ActionFilterAttribute
    {
        private static int _isExecuting = 0;
        private static int _isDuplicated = 0;
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (Interlocked.CompareExchange(ref _isExecuting, 1, 0) == 0)
            {
                base.OnActionExecuting(filterContext);
                return;
            }
            Interlocked.Exchange(ref _isDuplicated, 1);
            filterContext.Result = new StatusCodeResult((int)HttpStatusCode.ServiceUnavailable);
        }
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            base.OnResultExecuted(filterContext);
            if (_isDuplicated == 1)
            {
                Interlocked.Exchange(ref _isDuplicated, 0);
                return;
            }
            Interlocked.Exchange(ref _isExecuting, 0);
        }

最新更新