8

I have the following action method with async and await keywords:

[HttpPost]
public async Task<ActionResult> Save(ContactFormViewModel contactFormVM)
{
     if (domain.SaveContactForm(contactFormVM) > 0)// saves data in database
     {
         bool result = await SendMails(contactFormVM);//need to execute this method asynchronously but it executes synchronously
         return Json("success");
     }
         return Json("failure");
  }

    public async Task<bool> SendMails(ContactFormViewModel contactFormVM)
    {
            await Task.Delay(0);//how to use await keyword in this function?
            domain.SendContactFormUserMail(contactFormVM);
            domain.SendContactFormAdminMail(contactFormVM);
            return true;
    }

In the above code, once the database operation is finished I want to immediately return Json() result and then call the SendMails() method which should execute in the background. What changes should I make to the above code?

2
  • What error are you getting? Commented Apr 1, 2015 at 4:59
  • @utility I am not getting any error. The SendMails() method is executing synchronously instead of executing asynchronously. The return Json("success") should be called on the current thread and SendMails() should execute asynchronously.. Commented Apr 1, 2015 at 5:02

1 Answer 1

13

The await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. The task represents ongoing work.

It sounds like you don't want to wait for the result of SendMails. Think of async and await as tools to consume asynchronous APIs. Specifically, it's really useful to be able to "await" for the result of an "async" task. However, if you don't care about the result of your "async" (e.g. SendMails) task, then you don't need to "await" for the result (i.e. boolean).

Instead, you can simply use Task.Run to invoke your asynchronous task.

[HttpPost]
public async Task<ActionResult> Save(ContactFormViewModel contactFormVM) {
  if (domain.SaveContactForm(contactFormVM) > 0) {// saves data in database 
    Task.Run(() => SendMails(contactFormVM));
    return Json("success");
  }
  return Json("failure");
}

public void SendMails(ContactFormViewModel contactFormVM) {
  domain.SendContactFormUserMail(contactFormVM);
  domain.SendContactFormAdminMail(contactFormVM);
}
Sign up to request clarification or add additional context in comments.

5 Comments

this is exactly what I need and it seems to be working, but in the SendContactFormUserMail() function I am using StreamReader class to read the email template from a text file but I am getting Object reference not set to an instance of an object. exception..
It sounds like one of your variables is null. Answers to this question may help: stackoverflow.com/questions/779091/…
I am using HttpContext.Current.Server.MapPath() method to read a text file and the value for this is null in the async method...
Your HttpContext.Current is null because invoking asynchronous tasks will use a worker thread which does not have access to HttpContext.Current. There are a few questions that may help you. This is an example of a question/answer related to this problem: stackoverflow.com/questions/19111218/…
solved my issue using HostingEnvironment.ApplicationPhysicalPath; to get the application physical path and tested the code on server, working really fast now..thanks for the simple answer...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.