正确的方法异步发送ASP.NET中的电子邮件...(我是这样做对吗?) [英] Proper way to asynchronously send an email in ASP.NET... (am i doing it right?)

查看:180
本文介绍了正确的方法异步发送ASP.NET中的电子邮件...(我是这样做对吗?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的网站上用户登记,我不明白为什么我需要让他等待的SMTP让他得到一封激活邮件都要经过。

When a user registers on my website, I don't see why I need to make him "wait" for the smtp to go through so that he gets an activation email.

我决定,我希望异步推出这款code,它的是一个冒险。

I decided I want to launch this code asynchronously, and it's been an adventure.

让我想像有一个方法,如:

Lets imagine I have a method, such as:

private void SendTheMail() { // Stuff }

我的第一个,但..穿线。我这样做:

My first though.. was threading. I did this:

Emailer mailer = new Emailer();
Thread emailThread = new Thread(() => mailer.SendTheMail());
emailThread.Start();

这工作...直到我决定测试它的错误处理能力。我在web.config中故意打破了SMTP服务器地址,并尝试过。吓人的结果是,IIS基本上与w3wp.exe的未处理的异常错误B​​ARFED(这是Windows错误!多么极端......)ELMAH(我的错误记录器)没抓住和IIS重新启动,以便在网站上没有人有他们的会话删除。完全不能接受的结果!

This works... until I decided to test it for error-handling capability. I purposely broke the SMTP server address in my web.config and tried it. The scary result was that IIS basically BARFED with an unhandled exception error on w3wp.exe (it was a windows error! how extreme...) ELMAH (my error logger) did NOT catch it AND IIS was restarted so anyone on the website had their session erased. Completely unacceptable result!

我的下一个想法,就是做异步委托一些研究。这似乎更好地工作,因为异常是正在非同步委派内处理(不同于线程上面的例子)。但是,我很担心,如果我做错了或者我导致内存泄漏。

My next thought, was to do some research on Asynchronous delegates. This seems to work better because exceptions are being handled within the asynch delegate (unlike the thread example above). However, i'm concerned if i'm doing it wrong or maybe I'm causing memory leaks.

下面是我在做什么:

Emailer mailer = new Emailer();
AsyncMethodCaller caller = new AsyncMethodCaller(mailer.SendMailInSeperateThread);
caller.BeginInvoke(message, email.EmailId, null, null);
// Never EndInvoke... 

我这样做对吗?

推荐答案

有很多很好的意见,我upvoted在这里......如做一定要记得使用IDisposable接口(我完全不知道)。我也意识到它是多么重要,当手动赶在另一个线程错误,因为没有上下文 - 我一直在一种理论认为我应该让ELMAH处理一切。同时,进一步探索让我意识到,我忘了使用上的IDisposable MAILMESSAGE了。

There was a lot of good advice that I upvoted here... such as making sure to remember to use IDisposable (i totally didn't know). I also realized how important it is to manually catch errors when in another thread since there is no context -- I have been working on a theory that I should just let ELMAH handle everything. Also, further exploration made me realize I was forgetting to use IDisposable on mailmessage, too.

在回应理查德,虽然我看到线程解决方案可以工作(如在我的第一个例子建议),只要我赶上了错误...还是有一些可怕的关于彻底IIS的事实,如果爆炸了没有被捕获错误。这告诉我,ASP.NET/IIS从来就不是你这样做......这就是为什么我倾向于继续使用.BeginInvoke /代表替代,因为它不会弄乱IIS出问题的时候,似乎更受欢迎的ASP.NET。

In response to Richard, although I see that the threading solution can work (as suggested in my first example) as long as i'm catching the errors... there's still something scary about the fact that IIS completely explodes if that error isn't caught. That tells me that ASP.NET/IIS never meant for you to do that... which is why i'm leaning towards continuing to use .BeginInvoke/delegates instead since that doesn't mess up IIS when something goes wrong and seems to be more popular in ASP.NET.

在应对ASawyer,我完全惊讶,有内置的SMTP客户端.SendAsync。我打了那个解决方案一段时间,但它似乎并没有这样的伎俩我。虽然我可以通过code,做SendAsync,页面仍然是等待,直到SendCompleted事件完成的客户端跳过。我的目标是有,而电子邮件是在后台得到发送的用户和页面前进。我有一种感觉,我可能还在做错了什么......所以,如果有人经过这一点,他们可能会想尝试一下自己。

In response to ASawyer, I was totally surprised that there was a .SendAsync built into the SMTP client. I played with that solution for a while, but it doesn't seem to do the trick for me. Although I can skip through the client of code that does SendAsync, the page still "waits" until the SendCompleted event is done. My goal was to have the user and the page move forward while the email is getting sent in the background. I have a feeling that I might still be doing something wrong... so if someone comes by this they might want to try it themselves.

下面是我对我怎么除了与ELMAH.MVC错误日志发送的电子邮件100%异步完整的解决方案。我决定去与例2的扩展版本:

Here's my full solution for how I sent emails 100% asynchronously in addition with ELMAH.MVC error logging. I decided to go with an expanded version of example 2:

public void SendThat(MailMessage message)
{
    AsyncMethodCaller caller = new AsyncMethodCaller(SendMailInSeperateThread);
    AsyncCallback callbackHandler = new AsyncCallback(AsyncCallback);
    caller.BeginInvoke(message, callbackHandler, null);
}

private delegate void AsyncMethodCaller(MailMessage message);

private void SendMailInSeperateThread(MailMessage message)
{
    try
    {
        SmtpClient client = new SmtpClient();
        client.Timeout = 20000; // 20 second timeout... why more?
        client.Send(message);
        client.Dispose();
        message.Dispose();

        // If you have a flag checking to see if an email was sent, set it here
        // Pass more parameters in the delegate if you need to...
    }
    catch (Exception e)
    {
         // This is very necessary to catch errors since we are in
         // a different context & thread
         Elmah.ErrorLog.GetDefault(null).Log(new Error(e));
    }
}

private void AsyncCallback(IAsyncResult ar)
{
    try
    {
        AsyncResult result = (AsyncResult)ar;
        AsyncMethodCaller caller = (AsyncMethodCaller)result.AsyncDelegate;
        caller.EndInvoke(ar);
    }
    catch (Exception e)
    {
        Elmah.ErrorLog.GetDefault(null).Log(new Error(e));
        Elmah.ErrorLog.GetDefault(null).Log(new Error(new Exception("Emailer - This hacky asynccallback thing is puking, serves you right.")));
    }
}

这篇关于正确的方法异步发送ASP.NET中的电子邮件...(我是这样做对吗?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆