我正在尝试编写一个帮助类来在我的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
。
答案 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窗体中使用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
。