4

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

Main:调用发送邮件功能...
邮件发送:正在配置....
mailSend:设置不正确的端口....
mailSend:现在尝试发送....
邮件发送:行尾
主要:电子邮件功能调用完成。
主要:过程完成!
mailComp:发送邮件失败,将在 5 秒后重试...
mailComp:正在重试...
mailComp:发送成功!
mailComp:行尾

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

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

    protected void btnReset_Click(对象发送者,EventArgs e)
    {
        尝试
        {
            DataContext db = new DataContext();

            var query = 来自 db.Fish 中的 u
                        其中 u.Username == txtUsername.Text & u.Email == txtEmail.Text
                        选择新的 { u.Username, u.Email };

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


                用户用户 = 新用户();
                字符串令牌 = user.requestPasswordReset(txtUsername.Text);
                字符串 URL = Request.Url.AbsoluteUri.ToString() + "?token=" + token;
                String body = "如果您\n" + URL + "\n \n "则重置您的密码;


                untilty.SendEmail(txtEmail.Text, "重设密码", body);

                litTitle.Text = "消息已发送!";
                litInfo.Text = "请在几分钟后查看您的电子邮件以获取进一步说明。";
                视图模式(假,假);
            }
            别的
            {
                litCannotFindUserWithEmail.Visible = true;
            }


        }
        捕捉(例外前)
        {
            Debug.Write("主要:异常:" + ex.ToString());
            litInfo.Text = "我们目前遇到了一些技术上的困难。请稍后再试。如果您仍有问题,请致电 905344525";
        }
    }



///
公共静态类实用程序

///

    公共静态无效发送电子邮件(字符串收件人,字符串主题,字符串正文)
    {
        MailMessage 消息 = 新的 MailMessage();

        message.To.Add(new MailAddress(recipient));
        message.From = new MailAddress(fromaddress, "Basadur Profile Website");
        message.Subject = 主题;
        消息.正文 = 正文;

        发信息);
    }

    私人静态无效发送(MailMessage 消息)
    {
        SmtpClient smtp = new SmtpClient();
        smtp.Host = "smtp.gmail.com";
        smtp.Credentials = new System.Net.NetworkCredential(fromaddress, mailpassword);
        smtp.EnableSsl = true;
        Debug.WriteLine("mailSend: 设置了错误的端口....");
        smtp.端口 = 5872; //错误的端口
        smtp.SendCompleted += new SendCompletedEventHandler(smtp_SendCompleted);

        smtp.SendAsync(味精,味精);

    }

    静态无效 smtp_SendCompleted(对象发送者,System.ComponentModel.AsyncCompletedEventArgs e)
    {
        var msg = (MailMessage)e.UserState;

        如果(例如错误!= null)
        {
            System.Threading.Thread.Sleep(1000 * 5);

            尝试
            {
                SmtpClient smtp = new SmtpClient();
                smtp.Host = "smtp.gmail.com";
                smtp.Credentials = new System.Net.NetworkCredential(fromaddress, mailpassword);
                smtp.EnableSsl = true;
                smtp.端口 = 587;
                smtp.Send(msg);
            }
            捕捉(例外前)
            {
                Debug.WriteLine("mailComp: 第二次放弃失败。");
            }
        }

    }

4

5 回答 5

3

在 .NET 4.5.2 中,添加了一种用于在后台调度任务的方法,独立于任何请求:HostingEnvironment.QueueBackgroundWorkItem()

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

文档中的注释说:

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

这意味着,您可以以一种即发即弃的方式启动任务,并且更有信心在应用程序域回收时它不会被终止。

用法如下:

HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
    try 
    {
       // do work....
    }
    catch(Exception)
    {
        //make sure nothing can throw in here
    }
});
于 2016-02-16T19:47:07.543 回答
1

如今,您可以使用 Task 将工作分派到线程池。只需使用

Task.Run(()=>  Untilty.SendEmail(txtEmail.Text, "Reseting Password", body));
于 2018-01-12T13:10:51.593 回答
0

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

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

于 2011-06-29T16:36:04.933 回答
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);
                });
于 2016-08-04T20:18:25.637 回答
-3

使用线程:

// 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();

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

于 2011-06-29T15:02:20.497 回答