0

Please consider following scenario in an MVC website:

public JsonResult DoSomething()
{
    var result = PerformActionOne();
    _loggerService.LogActionAsync()
    return Json ({ Success = result });
}

The idea is to perform some action and log that the action happened. However, the log calls some third party api and regardless of if the action was logged, I want the code to continue running and return result. As such I do not care to wait for logging action to complete, I just want to call it and forget it.

Question:

Will this approach lead to a deadlock or another type of problem or maybe it is just considered bad practice and why? Does it differ between MVC5 and .NET 5?

Bagzli
  • 6,254
  • 17
  • 80
  • 163
  • You tagged both [tag:asp.net-mvc-5] and [tag:.net-5] which are completely different and incompatible products. Are you using ASP.NET Framework (looks like so) or ASP.NET Core 5? – Camilo Terevinto Dec 08 '21 at 17:54
  • I was wondering for both frameworks to be honest. I actually use both frameworks. I'll update the question – Bagzli Dec 08 '21 at 18:00
  • This is typically considered a bad practice since if the task aborts, you won't know. You should consider moving your logging to a background queue that is processed independently. That way, as long as your LogActionAsync call enqueues the data, the responsibility of this method is finished. – David L Dec 08 '21 at 18:15
  • @DavidL gotcha. For argument sake though outside of not knowing about the task aborting. Are there potential problems of deadlocks here or other issues that might cause website to go down if done in enough capacity or maybe return 404's, etc..? – Bagzli Dec 08 '21 at 18:17
  • It is impossible to say without knowing what the task is doing. Also, keep in mind that in .NET Framework there is a synchronization context and that there isn't one in .NET Core/.NET 5, which also can change the answer. In theory, no, it won't bring down the application but that's just as a general possibility and may change from case to case. – David L Dec 08 '21 at 18:19
  • I think the question here is: what would happen if your logger stops working. If logging is important to you, then wait for it to be completed. If not, don't use it at all. Also if your PerformActionOne() call fails, then you won't even be able to log something about the error. – Emre Utku Solak Dec 08 '21 at 18:42
  • Most loggers are probably already doing this for you by adding messages to a queue and flushing it on a background thread. If the logger you're using doesn't do that, then that's what you need to write - an implementation of the same logger service that flushes on a timer and/or when its buffer contains some maximum number of messages. That outer implementation could be decorator for the inner one. It buffers the messages and passes them to inner logger. – Scott Hannen Dec 08 '21 at 19:08
  • This is commonly called "fire and forget". You *can* do what you're doing, but there are consequences. A good explanation and alternative is in [this answer](https://stackoverflow.com/a/38101760/1202807). That said, if you really don't care if it succeeds, then keep doing what you're doing, but make sure that everything in `LogActionAsync()` is wrapped in `try` blocks so there's no chance of an unhandled exception. – Gabriel Luci Dec 08 '21 at 21:57

0 Answers0