静态助手方法的C#SmtpClient SendAsync?

时间:2015-02-26 19:18:38

标签: c# asp.net smtpclient

我正在尝试编写一个帮助类来在我的C#应用​​程序中发送电子邮件。我想使用SmtpClient.SendAsync,但显然我不了解异步的东西是如何工作的,或者我设置错了:

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);
    }
}

这会导致以下异常:

  

此时无法启动异步操作。异步   操作只能在异步处理程序中启动或   模块或在页面生命周期中的某些事件期间。如果这   执行页面时发生异常,确保页面为   标记为<%@ Page Async =“true”%>。此例外也可能表示   尝试调用“async void”方法,该方法通常不受支持   在ASP.NET请求处理中。相反,异步方法   应该返回一个Task,调用者应该等待它。

基于此异常,听起来我的SendMessage方法可能需要返回Task。但是,client.SendAsync返回无效,因此似乎没有任何Task返回或await

2 个答案:

答案 0 :(得分:3)

通用异步使用

要使用async方法,您的方法必须标记为async(一直到调用堆栈)。当你有异步方法时,你真的想避免使用void返回类型。大多数情况下,如果您的方法具有现有的返回类型,则应返回Task(或Task<T>。您还应该使用SendMailAsync,它使用基于任务的新异步方法。最后,您需要await调用异步方法。

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);
        }
    }
}

仅限Web窗体

在Web窗体中使用async有点棘手。您必须将页面标记为异步。

<%@ Page Async="true" %>

Web Forms的一个注意事项是,您无法更改返回Task for ASP.NET生命周期事件的方法。所以你需要注册任务。

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

但是,我们需要能够将消息传递给该函数。所以我们将使用lambda。

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

答案 1 :(得分:2)

您应该使用SendMailAsync(),它会返回Task