3

I am making a call to asynchronous operation with the following line of code:

Task.Run(() => { _emailService.SendEmail(email); }).Wait();


public async Task<bool> SendEmail(EmailTemplate email)
{
    try
    {
        using (Client)
        {
            await Client.SendMailAsync(email.Message);
            return true;
        }
    }
    catch (Exception ex)
    {
        Logger.Fatal(ex.ToString(), "Error occurred while sending an Email.");
        return false;
    }
}

When the code ran the first time, it worked without issues and I received my email, however when I run it every other time since I get the following 2 errors:

2016-02-04 15:50:05.3039 [11] FATAL ExceptionHandling.Models.EmailService+d__0.MoveNext - System.ObjectDisposedException: Cannot access a disposed object. Object name: 'System.Net.Mail.SmtpClient'. at System.Net.Mail.SmtpClient.SendAsync(MailMessage message, Object userToken) at System.Net.Mail.SmtpClient.SendMailAsync(MailMessage message) at ExceptionHandling.Models.EmailService.d__0.MoveNext()

2016-02-04 16:33:09.9768 [9] FATAL ExceptionHandling.Models.EmailService+d__0.MoveNext - System.Net.Mail.SmtpException: Failure sending mail. ---> System.InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.

I'm trying to understand why do I get the above errors after the first attempt?

Bagzli
  • 6,254
  • 17
  • 80
  • 163
  • One line of code?? What are we supposed to understand here? – Kosala W Feb 04 '16 at 21:41
  • 1
    Why do you start a task inside a `Task.Run` then immedatly `.Wait()` on it, you are wasting CPU resources by doing that. Just call the function directly. Also by looking at your call stack I bet you have a `async void` or you are calling a `.Result` or a `.Wait()` on the task returned from `SendMailAsync` which is possibly part of your problem. – Scott Chamberlain Feb 04 '16 at 21:43
  • @ScottChamberlain Can you give me an example of how that would look like? The only examples I found online were like the ones I used. – Bagzli Feb 04 '16 at 21:48
  • 1
    @Bagzli, here's a simple explanation of what you *should* be doing with async page methods in ASP.NET: http://www.hanselman.com/blog/TheMagicOfUsingAsynchronousMethodsInASPNET45PlusAnImportantGotcha.aspx – Kirill Shlenskiy Feb 04 '16 at 21:49

1 Answers1

5

Your error is probably (at least partly) due to you disposing your Client.

Disposing an object instantiated outside of the scope of the using statement is a pretty unconventional use of the keyword, and it's easy to get it wrong.

A simple fix would be to create a new client instance every time:

using (MailClient client = CreateMailClient())
{
    await client.SendMailAsync(email.Message);
    return true;
}

private SmtpClient CreateMailClient()
{
    MailClient client = new MailClient();

    // Configure client.

    return client;
}
Kirill Shlenskiy
  • 9,367
  • 27
  • 39