17

C # SmtpClient SendAsync from the Static Helper Method?

 3 years ago
source link: https://www.codesd.com/item/c-smtpclient-sendasync-from-the-static-helper-method.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

C # SmtpClient SendAsync from the Static Helper Method?

advertisements

I'm trying to write a helper class to send emails in my C# application. I would like to use SmtpClient.SendAsync, but apparently I'm not understanding how async stuff works or I have something set up wrong:

public class EmailService
{
    public static void SendMessage(MailMessage message)
    {
        var client = new SmtpClient("127.0.0.1", 25);
        client.SendCompleted += (s, e) =>
        {
            if (e.Error != null)
            {
                // TODO: Log the SMTP error somewhere
            }
            var callbackClient = s as SmtpClient;
            var callbackMessage = e.UserState as MailMessage;
            callbackClient.Dispose();
            callbackMessage.Dispose();
        };
        client.SendAsync(message, message);
    }
}

This results in the following exception:

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.

Based on this exception, it sounds like my SendMessage method probably needs to return a Task. However, client.SendAsync returns void so there doesn't appear to be any Task to return or await.


Generic async usage

To use async methods, your methods must be marked as async (all the way up the call stack). And when you have async method, you really want to avoid having a void return type. Most of the time you should return a Task (or a Task<T> if your method had an existing return type). You should also use SendMailAsync which uses the new Task based asynchronous approach. And lastly, you need to await your call to async methods.

public class EmailService
{
    public static async Task SendMessage(MailMessage message)
    {
        using (var client = new SmtpClient("127.0.0.1", 25))
        {
            await client.SendMailAsync(message, message);
        }
    }
}

For Web Forms Only

Using async in Web Forms is a little trickier. You must mark the page as async.

<%@ Page Async="true" %>

One thing you'll notice with Web Forms is that you can't change the methods to return a Task for ASP.NET lifecycle events. So you need to register the task.

public void Page_Load(object sender, EventArgs e)
{
    RegisterAsyncTask(new PageAsyncTask(SendMessage));
}

However, we need to be able to pass the message to the function. So we'll use a lambda.

public void Page_Load(object sender, EventArgs e)
{
    RegisterAsyncTask(new PageAsyncTask(() => EmailService.SendMessage(message)));
}


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK