.net 如何防止多个控制器动作的并发执行?

wi3ka0sx  于 2023-11-20  发布在  .NET
关注(0)|答案(2)|浏览(235)

该方法查询和聚合来自第三方API的结果,如果发出太多请求,该API可能会失控。
我考虑的方法是在Autofac中将控制器注册为单例,并使用锁来管理字段级变量的状态,该变量跟踪方法是否已经在进行中。
这是一个干净的实现还是它包含bug/竞争条件?

  1. public class ExpensiveController : Controller
  2. {
  3. private bool _alreadyRunning = false;
  4. private static readonly object Instancelock = new object();
  5. [HttpGet("expensiveController/CallThirdPartyApi")]
  6. public ActionResult<IEnumerable<MyObject>> CallThirdPartyApi()
  7. {
  8. // Critical Section Start
  9. lock (Instancelock)
  10. {
  11. if (_alreadyRunning == true)
  12. {
  13. return Ok
  14. }
  15. else
  16. {
  17. _alreadyRunning = true;
  18. }
  19. } //Critical Section End
  20. // do work
  21. var list = DoExpensiveProcessing()
  22. _alreadyRunning = false;
  23. return list;
  24. }
  25. }

字符串
下面是代码的清理版本,它使用一个静态字段来跟踪状态,而不是扰乱控制器的生命周期。

  1. public class ExpensiveController : Controller
  2. {
  3. private static bool _alreadyRunning;
  4. private static readonly object InstanceLock = new object();
  5. [HttpGet("expensiveController/CallThirdPartyApi")]
  6. public ActionResult<IEnumerable<MyObject>> CallThirdPartyApi()
  7. {
  8. lock (InstanceLock)
  9. {
  10. if (_alreadyRunning)
  11. {
  12. return new ServiceUnavailableResult();
  13. }
  14. _alreadyRunning = true;
  15. }
  16. var list = DoExpensiveProcessing()
  17. lock (InstanceLock)
  18. {
  19. _alreadyRunning = false;
  20. }
  21. return list;
  22. }
  23. }
  24. }

jslywgbw

jslywgbw1#

一个简单的版本可以是

  1. [HttpGet("expensiveController/CallThirdPartyApi")]
  2. public ActionResult<IEnumerable<MyObject>> CallThirdPartyApi()
  3. {
  4. lock
  5. {
  6. //your work
  7. }

字符串

3xiyfsfu

3xiyfsfu2#

我创建了一个库,可以帮助你实现你的目标。它叫做AsyncKeyedLock,可以通过NuGet获得。如果你使用DI注入一个AsyncKeyedLocker<string>单例,你就可以通过键锁定,其中键是控制器的名称。这样你就可以控制你想要对每个控制器进行多少并发调用。

相关问题