Question

I'm using TPL to send emails to the end-users without delaying the api response, i'm not sure which method should be used since im dealing with the db context here. I did method 2 because i wasn't sure that the db context would be available by the time the task gets to run, so a created a new EF object, or maybe im doing it all wrong.

public class OrdersController : ApiController {

    private AllegroDMContainer db = new AllegroDMContainer();

    public HttpResponseMessage PostOrder(Order order) {

        // Creating a new EF object and adding it to the database
        Models.Order _order = new Models.Order{ Name = order.Name };
        db.Orders.Add(_order);

        /* Method 1 */
        Task.Factory.StartNew(() => {
            _order.SendEmail();
        });

        /* Method 2 */
        Task.Factory.StartNew(() => {
            Models.Order rOrder = db.Orders.Find(_order.ID); 
            rOrder.SendEmail();
        });

        return Request.CreateResponse(HttpStatusCode.Created);

    }


}
Was it helpful?

Solution

Both methods are wrong, because you're starting a fire-and-forget operation on a pool thread inside the ASP.NET process.

The problem is, an ASP.NET host is not guaranteed to stay alive between handling HTTP responses. E.g., it can be automatically recycled, manually restarted or taken out of the farm. In which case, the send-mail operation would never get completed and you wouldn't get notified about it.

If you need to speed up the response delivery, consider outsourcing the send-mail operation to a separate WCF or Web API service. A related question: Fire and forget async method in asp.net mvc.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top