3

I'm using the attribute [OutputCache(Duration=XXX)] (and also the donut variant [DonutOutputCache(Duration=XXX)]).

However I noticed (confirmed by ASP.NET (MVC) Outputcache and concurrent requests) this is not thread safe: when the cache is re-generated, if the controller method is slow enough (and it's usually the case, this is why you cache it ^^), multiple "identical" requests can enter the action an perform the operations, instead of having only 1 request processed, blocking the other requests and serving them from the cache.

Is there any way to easily make a blocking/thread safe OutputCache attribute? Same question for DonutOutputCache? Like [BlockingOutputCache(SameParameters)] and [BlockingDonutOutputCache(SameParameters)]

Note: cached actions are regular actions, returning View(model), heavy work is done in the action and in the view (the view can do something very simple like @Model.GetPrice() which translates to heavy lifting in the backend).

Thanks!

Edit: another way could be to create a [BlockingAction(BlockingParameters)] attribute that would block subsequent requests to this action when not served from the cache.

Community
  • 1
  • 1
Vincent
  • 938
  • 13
  • 20

1 Answers1

1

You could use the VaryByCustom. In Global.asax override the GetVaryByCustomString method. Then create unique cache key, and use double checked locking on your cache storage. It's sync way. I may guess that exists async way when you begin cache resolving and then end cache resolving.

sh1ng
  • 2,808
  • 4
  • 24
  • 38
  • This is actually pretty smart and doesn't requires lot of changes! I'll try to figure out the details (I might create a special attribute, I don't exactly now what I'm gonna do yet) and keep this question up to date. Thanks for your answer! – Vincent Oct 18 '13 at 19:18
  • I +'d it, but it's too generic to be the "accepted" answer, sorry. – Vincent Oct 27 '13 at 13:39