Использование Asp.Net для отправки электронной почты SendAsync, но Page все еще ждет? - PullRequest
4 голосов
/ 29 июня 2011

Я не хочу, чтобы пользователь ждал страницы, завершающей процессы отправки, поэтому я подумал об использовании SendAsync в ASP.NET 3.5. Но после отладки я обнаружил, что Main Thread все еще ждет.

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 завершена, происходит окончательная публикация страницы. Это какое-то ограничение для 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 ]

3 голосов
/ 16 февраля 2016

В .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
    }
});
1 голос
/ 12 января 2018

В наши дни вы можете использовать Задачу для отправки работы в пул потоков.Просто используйте

Task.Run(()=>  Untilty.SendEmail(txtEmail.Text, "Reseting Password", body));
0 голосов
/ 04 августа 2016

Используя приведенный ниже код, вы можете отправлять асинхронные электронные письма в asp.net с SmtpClient.

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);
                });
0 голосов
/ 29 июня 2011

Отладчик, кажется, заставляет вещи быть однопоточными.Если вы пройдете через него, вы можете обнаружить, что переходите между двумя разными файлами, поскольку каждый шаг перемещает отдельную нить.

Попробуйте добавить туда вход в систему и запустить без отладки.

0 голосов
/ 29 июня 2011

Использовать потоки:

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

Здесь - источник, у него есть полное руководство по потокам.

...