当前位置: 首页 > 编程语言 > C#

ASP.NET异步发送邮件的正确方式...(我做对了吗?)分享

时间:2023-04-11 10:37:49 C#

ASP.NET异步发送邮件的正确方式...(我做对了吗?)?)当用户在我的网站上注册时,我不明白为什么我需要让他“等待”smtp通过才能获得激活电子邮件。我决定异步启动这段代码,这是有风险的。假设我有一个类似的方法:privatevoidSendTheMail(){//Stuff}我的第一个方法是线程。我这样做了:Emailermailer=newEmailer();线程emailThread=newThread(()=>mailer.SendTheMail());emailThread.Start();这很有效……直到我决定测试它的错误处理能力。我故意把我的web.config中的SMTP服务器地址弄坏了试了一下。可怕的结果是IIS基本上因w3wp.exe上的未处理异常错误而被阻止(这是一个Windows错误!多么极端......)ELMAH(我的错误记录器)没有捕捉到它并且IIS重新启动所以网站上没有任何东西每个人都有删除了他们的会话。完全不能接受的结果!我的下一个想法是,对异步委托进行一些研究。这似乎工作得更好,因为异常是在异步委托中处理的(与上面的线程示例不同)。但是,我担心的是我是否做错了或者是否可能导致内存泄漏。这就是我正在做的:Emailermailer=newEmailer();AsyncMethodCaller调用者=newAsyncMethodCaller(mailer.SendMailInSeperateThread);caller.BeginInvoke(message,email.EmailId,null,null);//NeverEndInvoke...是我做的吗?我在这里投票赞成很多好的建议......比如确保记住使用IDisposable(我完全不知道)。我也意识到在另一个线程中手动捕获错误是多么重要,因为没有上下文——我一直在研究一个理论,我应该让ELMAH处理所有事情。此外,进一步探索让我意识到我忘记在邮件消息上使用IDisposable。作为对Richard的回应,虽然我已经看到线程解决方案有效(如我的第一个示例),但只要我发现错误...如果错误没有发现,IIS完全崩溃的事实仍然令人恐惧。捕捉。这告诉我ASP.NET/IIS从来没有让你这样做……这就是为什么我倾向于继续使用.BeginInvoke/delegates的原因,因为它不会在出现问题时与IIS混淆,而且在ASP中似乎更多.NET流行。作为对ASawyer的回应,我对SMTP客户端内置了.SendAsync感到非常惊讶。我尝试了一段时间的解决方案,但它似乎对我不起作用。虽然我可以跳过执行SendAsync的代码客户端,但页面仍然“等待”直到SendCompleted事件完成。我的目标是在后台发送电子邮件的同时让用户和页面向前移动。我有一种感觉,我可能仍然做错了什么……所以如果有人来这里,他们可能想自己尝试一下。这是我使用ELMAH.MVC错误记录100%异步发送电子邮件的完整解决方案。我决定使用示例2的扩展版本:publicvoidSendThat(MailMessagemessage){AsyncMethodCallercaller=newAsyncMethodCaller(SendMailInSeperateThread);AsyncCallbackcallbackHandler=newAsyncCallback(AsyncCallback);caller.BeginInvoke(消息,callbackHandler,null);}私有委托voidAsyncMethodCaller(MailMessagemessage);privatevoidSendMailInSeperateThread(MailMessagemessage){try{SmtpClientclient=newSmtpClient();client.Timeout=20000;//20秒超时...为什么更多?客户端。发送(消息);客户端.Dispose();消息.Dispose();//如果你有一个标志来检查是否发送了电子邮件,请在此处设置它//如果需要,请在委托中传递更多参数...}catch(Exceptione){//这对于捕获错误非常必要因为我们在//不同的上下文和线程Elmah.ErrorLog.GetDefault(null).Log(newError(e));}}privatevoidAsyncCallback(IAsyncResultar){try{AsyncResult结果=(AsyncResult)ar;AsyncMethodCaller调用者=(AsyncMethodCaller)result.AsyncDelegate;呼叫者.EndInvoke(ar);}catch(Exceptione){Elmah.ErrorLog.GetDefault(null).Log(newError(e));Elmah.ErrorLog.GetDefault(null).Log(newError(newException("Emailer-Thishackyasynccallbackthingispoking,servesyouright.")));从.NET4.5开始,SmtpClient实现了async-await方法SendMailAsync所以,异步发送邮件如下:message.To.Add(toEmailAddress);message.Subject=emailSubject;message.Body=emailMessage;使用(varsmtpClient=newSmtpClient()){awaitsmtpClient.SendMailAsync(message);您是否使用.NetSmtpClient发送电子邮件?它可以发送异步消息。编辑-我想如果Emailermailer=newEmailer();这不会有用不是SmtpClient的包装器。线程在这里不是错误的选择,但如果您不自己处理异常,它会冒泡并使您的进程崩溃。你做哪个线程并不重要。所以代替mailer.SendTheMail()试试这个:newThread(()=>{try{mailer.SendTheMail();}catch(Exceptionex){//Dosomethingwiththeexception}});更好的是,如果可以的话,使用SmtpClient的异步功能。您仍然需要处理异常。我什至会建议您查看.Net4的新Parallet任务库。它具有允许您处理异常情况并与ASP.Net的线程池一起工作的附加功能。如果您使用.Net的SmtpClient和MailMessage类,则有几件事您应该注意。首先,预计会发送错误,因此捕获并处理它们。其次,在.Net4中,这些类发生了一些变化,它们现在都实现了IDisposable(MailMessage自3.5以来,新的SmtpClient在4.0中)。因此,您应该使用块或显式处理来创建SmtpClient和MailMessage。这是一些人不知道的重大变化。有关使用异步发送时处理的更多信息,请参阅此SO问题:WhatarethebestpracticesforusingSmtpClient,SendAsyncandDisposeunder.NET4.0那么,为什么不使用单独的轮询/服务来发送电子邮件呢?因此,允许您的注册回发仅在写入数据库/消息队列所需的时间内执行,并将发送电子邮件延迟到下一个轮询间隔。我刚才也在想同样的问题,我想我什至不想在服务器回发请求中发起电子邮件发送。为网页提供服务的过程应该对尽快返回给用户感兴趣,您尝试做的越多,速度就越慢。查看命令查询隔离主体(http://martinfowler.com/bliki/CQRS.html)。MartinFowler解释说,在查询部分使用的操作的命令部分可以使用不同的模型。在这种情况下,命令将是“注册用户”,查询将是激活电子邮件,使用一个松散的类比。相关引用可能是:通过单独的模型,我们通常表示不同的对象模型,可能在不同的逻辑过程中运行另外值得一读的是关于CQRS的维基百科文章(http://en.wikipedia.org/wiki/Command%E2%80%93query_separation)。这个亮点的一个要点:它显然是作为一种编程指南而不是一种良好的编码规则含??义,在代码、程序执行和程序员理解会受益的地方使用它。这是一个很好的示例场景。这种方法的另一个好处是它消除了所有多线程问题和随之而来的麻烦。我在我的项目上遇到了同样的问题:第一次尝试像你这样的线程:-我松散了背景-异常处理问题-一般来说,线程在IIS线程池上是个坏主意所以我切换并异步尝试:-“异步”在asp.net网络应用程序。它只是放入队列调用并打开上下文,所以我通过sql表创建Windows服务并检索值:happyend所以为了快速解决方案:从ajax端进行异步调用以告诉用户假的是,但继续你的mvc控制器发送作业使用这种方式-privatevoidemail(objectparameters){ArrayarrayParameters=newobject[2];arrayParameters=(数组)参数;字符串电子邮件=(字符串)arrayParameters.GetValue(0);stringsubjectEmail=(string)arrayParameters.GetValue(1);if(Email!="Email@email.com"){OnlineSearchOnlineResult=newOnlineSearch();尝试{StringBuilderstr=newStringBuilder();MailMessagemailMessage=newMailMessage();//这里我们设置地址mailMessage.From=fromAddress;mailMessage.To.Add(Email);//这里可以添加多个emailidmailMessage.Subject="";//这里我们设置添加密件抄送地址//mailMessage.Bcc.Add(newMailAddress("bcc@site.com"));海峡追加(“”);海峡追加(“”);海峡追加(“”);海峡追加(“”);海峡追加(“”);海峡追加(“”);//判断邮件正文是否为htmlmailMessage.IsBodyHtml=true;mailMessage.Body=str.ToString();//此电子邮件的文件附件。附件attach=newAttachment();mailMessage.Attachments.Add(附件);mailClient.Send(mailMessage);}}protectedvoidbtnEmail_Click(objectsender,ImageClickEventArgse){try{stringTo=txtEmailTo.Text.Trim();字符串[]参数=新字符串[2];参数[0]=至;参数[1]=PropCase(ViewState["StockStatusSub"].ToString());线程SendingThreads=newThread(email);SendingThreads.Start(参数);lblEmail.Visible=true;lblEmail.Text="邮件发送成功";如果你想检测泄漏,你需要使用这样的分析器:http://memprofiler。com/我没有发现您的解决方案有任何问题,但它几乎可以保证您的问题将被视为主观的。另一种选择是使用jQuery对服务器进行ajax调用并启动电子邮件流。这样,UI就不会被锁定。祝你好运!以上就是C#学习教程:在ASP.NET中异步发送邮件的正确方法...(我做对了吗?)全部内容分享出来,如果对你有用需要进一步了解C#学习教程,希望大家多多关注——本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:

最新推荐
猜你喜欢