我正在尝试从我的MVC应用程序发送电子邮件,它在我使用.Send()方法时发送正常,但需要一段时间才能返回,所以我想使用.SendMailAsync()函数,但我收到以下错误执行.
此时无法启动异步操作.异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动.如果在执行页面时发生此异常,请确保将页面标记为<%@ Page Async ="true"%>
这是我的代码示例.我如何配置它以使用.SendMailAsync()发送
电子邮件包装类:
using System.Net.Mail;
namespace Helpers
{
public class Email
{
// constants
private const string HtmlEmailHeader = "<html><head><title></title></head><body style='font-family:arial; font-size:14px;'>";
private const string HtmlEmailFooter = "</body></html>";
// properties
public List<string> To { get; set; }
public List<string> CC { get; set; }
public List<string> BCC { get; set; }
public string From { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
// constructor
public Email()
{
To = new List<string>();
CC = new List<string>();
BCC = new List<string>();
}
// send
public void Send()
{
MailMessage message = new MailMessage();
foreach (var x in To)
{
message.To.Add(x);
}
foreach (var x in CC)
{
message.CC.Add(x);
}
foreach (var x in BCC)
{
message.Bcc.Add(x);
}
message.Subject = Subject;
message.Body = string.Concat(HtmlEmailHeader, Body, HtmlEmailFooter);
message.BodyEncoding = System.Text.Encoding.UTF8;
message.From = new MailAddress(From);
message.SubjectEncoding = System.Text.Encoding.UTF8;
message.IsBodyHtml = true;
SmtpClient client = new SmtpClient("relay.mail.server");
client.SendMailAsync(message);
}
}
}
Run Code Online (Sandbox Code Playgroud)
控制器:
public ActionResult Index()
{
Email email = new Email();
email.To.Add("to@email.com");
email.From = "from@email.com";
email.Subject = "Subject";
email.Body = "<p><strong>Hello</strong></p><p>This is my first Email Message</p>";
email.Send();
}
Run Code Online (Sandbox Code Playgroud)
编辑
除了问的实际问题,潜在的问题是发送电子邮件时产生的延迟.我在这篇文章的帮助下进一步研究了实际问题:
修改了我的Email Wrapper类以生成一个新线程来执行电子邮件处理:
using System.Net.Mail;
namespace Helpers
{
public class Email
{
// constants
private const string HtmlEmailHeader = "<html><head><title></title></head><body style='font-family:arial; font-size:14px;'>";
private const string HtmlEmailFooter = "</body></html>";
// properties
public List<string> To { get; set; }
public List<string> CC { get; set; }
public List<string> BCC { get; set; }
public string From { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
// constructor
public Email()
{
To = new List<string>();
CC = new List<string>();
BCC = new List<string>();
}
// send
public void Send()
{
MailMessage message = new MailMessage();
foreach (var x in To)
{
message.To.Add(x);
}
foreach (var x in CC)
{
message.CC.Add(x);
}
foreach (var x in BCC)
{
message.Bcc.Add(x);
}
message.Subject = Subject;
message.Body = string.Concat(HtmlEmailHeader, Body, HtmlEmailFooter);
message.BodyEncoding = System.Text.Encoding.UTF8;
message.From = new MailAddress(From);
message.SubjectEncoding = System.Text.Encoding.UTF8;
message.IsBodyHtml = true;
SmtpClient client = new SmtpClient("relay.mail.server");
new Thread(() => { client.Send(message); }).Start();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*att 68
不可否认,错误有点迟钝,但它真正告诉你的是你从同步方法调用异步方法,这是不允许的.如果您要使用异步,则必须在链的整个过程中使用异步.
因此,首先需要更改Send方法定义以返回Task:
public async Task Send()
Run Code Online (Sandbox Code Playgroud)
并将您的异步方法调用设置为等待:
await client.SendMailAsync(message);
Run Code Online (Sandbox Code Playgroud)
然后,为您的行动做同样的事情:
public async Task<ActionResult> Index()
Run Code Online (Sandbox Code Playgroud)
和:
await email.Send();
Run Code Online (Sandbox Code Playgroud)
UPDATE
异步不会做我认为你认为它做的事情.当您的操作被请求调用时,它将不会返回响应,直到操作中的所有代码完全执行.异步不是一个魔术棒,使动作更快地返回响应.您的任务(在这种情况下,发送电子邮件)需要花费的时间和异步与否,在任务完成之前,操作不会返回响应.
那么为什么要使用异步呢?因为异步的作用是从服务器池中释放线程.假设IIS在一个非常标准的配置中运行,你可能会有大约1000个线程可用.这通常称为"最大请求",因为通常1个请求== 1个线程.因此,如果您的服务器负载很重并且您的部署超过"最大请求数",则每个后续请求都会排队,直到来自池的线程再次可用.如果所有线程都在等待某些东西完成,那么你的服务器基本上就会死锁.但是,当你使用async时,你告诉IIS本质上,"我正在等待某些东西.这是我的线程,所以你可以用它来记录另一个请求.我会在需要时通知你." 这允许队列中的请求继续进行.
无论长短,当你做任何涉及等待的事情时都要始终使用异步,因为它可以更有效地使用服务器资源,但请记住它不能让事情更快地发生.
编辑12/11/14 - 稍微更新了术语,以明确异步仅在线程等待时有用,而不仅仅涉及一些长时间运行的任务.例如,运行复杂的财务计算可能"需要一段时间",但不适合异步,因为所有工作都受CPU限制.该任务可能是长时间运行的,但如果该线程未处于等待状态,则它不能用于其他任务,并且您的异步方法基本上只是作为同步运行,但需要额外的开销.
| 归档时间: |
|
| 查看次数: |
34251 次 |
| 最近记录: |