使用Asp.Net发送SendAsync电子邮件,但Page仍在等待?

时间:2011-06-29 14:56:06

标签: c# asp.net .net-3.5 asynchronous sendasync

我不希望用户等待页面完成发送过程,所以我想在ASP.NET 3.5中使用SendAsync。但是在调试之后,我发现主线程仍然等待。

Main: Call send email function...
mailSend: Configuring....
mailSend: setting up incorrect port....
mailSend: Attempt now to send....
mailSend: End of Line
Main: Email Function call finish.
Main: Proccess Complete!
mailComp: Sending of mail failed, will try again in 5 seconds...
mailComp: Retrying...
mailComp: Send successful!
mailComp: End of Line

现在我放置了错误的端口设置,因此第一封电子邮件失败,并测试第二次是否成功。即使使用正确的端口,页面仍然等待。只有在mailComp函数完成后才会最终发布Page。这是SendAsyn的一些限制吗?

这里有一些代码,不确定这是否有用。


    protected void btnReset_Click(object sender, EventArgs e)
    {
        try
        {
            DataContext db = new DataContext();

            var query = from u in db.Fish
                        where u.Username == txtUsername.Text & u.Email == txtEmail.Text
                        select new { u.Username, u.Email };

            if (query.Count() != 0)
            {


                User user = new User();
                String token = user.requestPasswordReset(txtUsername.Text);
                String URL = Request.Url.AbsoluteUri.ToString() + "?token=" + token;
                String body = "Reseting you password if you \n" + URL + "\n \n ";


                Untilty.SendEmail(txtEmail.Text, "Reseting Password", body);

                litTitle.Text = "Message was sent!";
                litInfo.Text = "Please check your email in a few minuets for further instruction.";
                viewMode(false, false);
            }
            else
            {
                litCannotFindUserWithEmail.Visible = true;
            }


        }
        catch (Exception ex)
        {
            Debug.Write("Main: Exception: " + ex.ToString());
            litInfo.Text = "We are currently having some technically difficulty. Please try  again in a few minuets. If you are still having issue call us at 905344525";
        }
    }



///
public static class Utility

///

    public static void SendEmail(string recipient, string subject, string body)
    {
        MailMessage message = new MailMessage();

        message.To.Add(new MailAddress(recipient));
        message.From = new MailAddress(fromaddress, "Basadur Profile Website");
        message.Subject = subject;
        message.Body = body;

        Send(message);
    }

    private static void Send(MailMessage msg)
    {
        SmtpClient smtp = new SmtpClient();
        smtp.Host = "smtp.gmail.com";
        smtp.Credentials = new System.Net.NetworkCredential(fromaddress, mailpassword);
        smtp.EnableSsl = true;
        Debug.WriteLine("mailSend: setting up incorrect port....");
        smtp.Port = 5872; //incorrect port
        smtp.SendCompleted += new SendCompletedEventHandler(smtp_SendCompleted);

        smtp.SendAsync(msg, msg);

    }

    static void smtp_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        var msg = (MailMessage)e.UserState;

        if (e.Error != null)
        {
            System.Threading.Thread.Sleep(1000 * 5);

            try
            {
                SmtpClient smtp = new SmtpClient();
                smtp.Host = "smtp.gmail.com";
                smtp.Credentials = new System.Net.NetworkCredential(fromaddress, mailpassword);
                smtp.EnableSsl = true;
                smtp.Port = 587;
                smtp.Send(msg); 
            }
            catch (Exception ex)
            {
                Debug.WriteLine("mailComp: Failed for the second time giving up.");
            }
        }

    }

5 个答案:

答案 0 :(得分:3)

在.NET 4.5.2中,添加了一种方法,用于在后台安排任务,与任何请求无关:HostingEnvironment.QueueBackgroundWorkItem()

HostingEnvironment.QueueBackgroundWorkItem()位于System.Web.Hosting命名空间中。

文件中的评论说:

  

与ASP.NET中可以保留的普通ThreadPool工作项不同   跟踪当前通过此API注册的工作项数   运行,并且ASP.NET运行时将尝试延迟AppDomain关闭   直到这些工作项目完成执行。

意思是,您可以以一种即发即忘的方式启动任务,并且在应用程序域回收时不会被终止。

用法如下:

HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
    try 
    {
       // do work....
    }
    catch(Exception)
    {
        //make sure nothing can throw in here
    }
});

答案 1 :(得分:1)

现在,您可以使用Task将工作分派给线程池。只需使用

Task.Run(()=>  Untilty.SendEmail(txtEmail.Text, "Reseting Password", body));

答案 2 :(得分:0)

调试器似乎强迫事物是单线程的。如果您单步执行,您可能会发现最终在两个不同的文件之间跳转,因为每个步骤移动一个不同的线程。

尝试在那里添加一些日志记录并在不调试的情况下运行。

答案 3 :(得分:0)

使用以下代码,您可以使用SmtpClient在asp.net中发送异步电子邮件。

ThreadPool.QueueUserWorkItem(callback =>
                {
                    var mailMessage = new MailMessage
                    {
                        ...
                    };

                    //if you need any references in handlers
                    object userState = new ReturnObject
                    {
                        MailMessage = mailMessage,
                        SmtpClient = smtpServer
                    };
                    smtpServer.SendCompleted += HandleSmtpResponse;
                    smtpServer.SendAsync(mailMessage, userState);
                });

答案 4 :(得分:-2)

使用线程:

// Create the thread object, passing in the method
  // via a ThreadStart delegate. This does not start the thread.
  Thread oThread = new Thread(new ThreadStart(SendMyEmail));

  // Start the thread
  oThread.Start();

Here是源代码,它有一个完整的线程教程。