C# 在ASP.NET C中异步发送电子邮件#
我想知道是否有一种方法可以在asp.net c#中异步发送电子邮件。我使用以下代码发送电子邮件:C# 在ASP.NET C中异步发送电子邮件#,c#,asp.net,email,asynchronous,C#,Asp.net,Email,Asynchronous,我想知道是否有一种方法可以在asp.net c#中异步发送电子邮件。我使用以下代码发送电子邮件: if (checkObavijest.Checked) { List<hsp_Kupci_Newsletter_Result> lista = ServisnaKlasa.KupciNewsletter(); for (int i = 0; i < lista.Count; i++)
if (checkObavijest.Checked)
{
List<hsp_Kupci_Newsletter_Result> lista = ServisnaKlasa.KupciNewsletter();
for (int i = 0; i < lista.Count; i++)
{
MailMessage mail = new MailMessage();
mail.From = new MailAddress("*******");
mail.To.Add(lista[i].Email);
mail.Subject = "Subject";
mail.SubjectEncoding = Encoding.UTF8;
mail.BodyEncoding = Encoding.UTF8;
mail.IsBodyHtml = true;
mail.Priority = MailPriority.High;
mail.Body = "Some message";
SmtpClient smtpClient = new SmtpClient();
Object state = mail;
smtpClient.Credentials = new NetworkCredential("****@gmail.com", "****");
smtpClient.Port = 587;
smtpClient.Host = "smtp.gmail.com";
smtpClient.EnableSsl = true;
smtpClient.SendCompleted += new SendCompletedEventHandler(smtpClient_SendCompleted);
try
{
smtpClient.SendAsync(mail, state);
}
catch (Exception ex)
{
}
}
void smtpClient_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
MailMessage mail = e.UserState as MailMessage;
if (!e.Cancelled && e.Error != null)
{
string poruka = "Emailovi poslani!";
ClientScript.RegisterStartupScript(this.GetType(), "myalert", "alert('" + poruka + "');", true);
}
}
if(选中obavijest.Checked)
{
List lista=ServisnaKlasa.KupciNewsletter();
for(int i=0;i
但是,当我选择发送电子邮件时,页面加载时间大约为40秒,然后在40秒后发送电子邮件。正如你所看到的,我正在从数据库中取出20-30封电子邮件。我认为这是异步发送邮件的正确方法,但显然不是……我如何将电子邮件发送推送到另一个线程呢esn不会影响正在使用此页面的用户吗?有人能帮我解决吗?谢谢!原因在下面的 调用SendAsync后,必须等待电子邮件传输成功 在尝试使用“发送”发送另一封电子邮件之前完成 或者SendAsync 您可以使用
ThreadPool
通过包装的方法调用SendAsync
。这会给您带来类似于火灾和遗忘场景的效果
大概是这样的:
public void SendViaThread(System.Net.Mail.MailMessage message) {
try {
System.Threading.ThreadPool.QueueUserWorkItem(SendViaAsync, message);
} catch (Exception ex) {
throw;
}
}
private void SendViaAsync(object stateObject) {
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient();
System.Net.Mail.MmailMessage message = (MmailMessage)stateObject;
...
smtp.Credentials = new NetworkCredential("...");
smtp.Port = 587;
smtp.Host = "...";
...
smtp.SendCompleted += new SendCompletedEventHandler(smtpClient_SendCompleted);
...
smtp.Send(message);
}
您可以在代码中调用SendViaThread(mail)
。因此,您的循环现在变成:
for (int i = 0; i < lista.Count; i++) {
MailMessage mail = new MailMessage();
mail.From = new MailAddress("...");
mail.To.Add(lista[i].Email);
mail.Subject = "...";
...
mail.Body = "...";
SendViaThread(mail);
}
for(int i=0;i
如果不想让主线程等待,请尝试在任务中丢弃它
Task.Factory.StartNew( () => {
// do mail stuff here
});
请注意,尽管每次生成任务时,都会生成一个新的(或重复使用)系统已生成的线程。如果要发送30封电子邮件,则可能会发送很多线程(系统也有一个可编程的cap)。task.Factory.StartNew
是执行“先发后忘”过程的一种非常简单的方法
(在本例中,代码还保留了一组
任务
,如果您愿意管理它们,这很好——但实际上,您只需要Task.Factory.StartNew(()=>{
bit,如果您想启动并忘记。请小心,因为您不想让孤立线程与内存使用率挂钩。我会尝试一下,但为什么您要将sendviathread函数声明为bool,为什么不作废?哦..这是我的一个项目中代码的一部分..我正在做更多的工作并返回bool以指示问题。您我真的不需要。谢谢你指出,我将删除该部分。你能更具体地说明我如何将其构建到我现有的代码中吗?我不太确定我应该在这里做什么…@perkes456:我已经让答案更清楚了。你所要做的就是删除现有循环中的smtpclient
相关代码,然后调用SendViaThread(mail)
而不是smtpClient.SendAsync(mail,state)
我应该这样做:对象状态=mail;试试{SendViaAsync(state);SendViaThread(mail);}还是试试{SendViaThread(mail);}哪一个?有没有什么方法可以在这些线程发送完邮件后处理它们…不是真的,你可以让系统处理释放这些任务。一旦它们完成,它们就完成了。--请看以下内容:作为旁白,你也可以使用Task.Run(而不是.StartNew)--也要注意这一点。如果您想了解跟踪任务的情况,可以将它们添加到所列示例中的集合中,或者在启动时使用将它们包装在中(使用清理自身及其局部).但我建议只让.NET处理清理,而不要为此烦恼。过去,我在集合中添加了衍生线程,这样我就可以监视它们的进程、它们在做什么,并能够在需要时删除它们(多线程是一个有趣的[不是]世界).Task.Run/StartNew使您不必太担心线程状态、竞态条件等,就可以轻松地解决问题。这非常适合您的fire and forget场景。使用问题中发布的第一个代码,我遇到了一个“内存不足”的错误,这可能是错误的原因吗?