C# MailSender и спать

Я пишу программу, которая отправляет электронную почту через класс SmtpClient. Я использую этот код:

        try
        {
            MailMessage mail = new MailMessage();
            SmtpClient SmtpServer = new SmtpClient("mailSMTP.it");

            mail.From = new MailAddress("address.it");

            mail.Subject = "oggetto";

            mail.IsBodyHtml = true;
            string htmlBody = "someHTML";

            mail.Body = htmlBody;

            SmtpServer.Port = 25;

            SmtpServer.EnableSsl = false;

            foreach (string indirizzo in indirizzi)
            {
                mail.To.Clear();
                mail.To.Add(indirizzo);
                SmtpServer.Send(mail);
                System.Threading.Thread.Sleep(3000);
            }

            MessageBox.Show("e-mail spedite!");

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }

но это работает, только если я пересекаю линию "Sleep". Зачем? Я думал, что это хорошая идея, чтобы отдохнуть во время этого процесса.

5 ответов

Учитывая, что есть исключение, при условии, что это по вызову Send Я бы предложил не использовать повторно MailMessage объект и создание нового на каждой итерации цикла. например:

        //...
        foreach (string indirizzo in indirizzi)
        {
            string htmlBody = "someHTML";
            MailMessage mail = new MailMessage 
            {
                From = new MailAddress("address.it"),
                Subject = "oggetto",
                IsBodyHtml = true,
                Body = htmlBody,
            };

            mail.To.Clear();
            mail.To.Add(indirizzo);
            SmtpServer.Send(mail);
        }

Если под "работами" вы подразумеваете MessageBox появляется в разумные сроки... то причина в том, что Sleep блокирует поток пользовательского интерфейса, пока все сообщения не будут отправлены. например, если вы попытаетесь отправить 10 сообщений, пользовательский интерфейс остановится на 30 секунд (3000 миллисекунд X 10).

На мой взгляд (и другие) вы должны стараться избегать Sleep практически любой ценой, чаще всего вы получаете приложение, которое ведет себя странно (например, поведение, которое вы описываете).

Я бы решил это с помощью таймера, который использует индекс, чтобы определить, какое из следующих писем будет отправлено. Что-то вроде этого:

    try
    {
        MailMessage mail = new MailMessage();
        SmtpClient SmtpServer = new SmtpClient("mailSMTP.it");

        mail.From = new MailAddress("address.it");

        mail.Subject = "oggetto";

        mail.IsBodyHtml = true;
        string htmlBody = "someHTML";

        mail.Body = htmlBody;

        SmtpServer.Port = 25;

        SmtpServer.EnableSsl = false;

        var index = 0;

        var timer = new System.Threading.Timer((callbackState) =>
            {
                mail.To.Clear();
                mail.To.Add(indirizzi[index]);
                SmtpServer.Send(mail);

                index++;

                if (index < indirizzi.Count)
                  timer.Change(3000, Timeout.Infinite);
                else {
                    timer.Dispose();
                    Invoke(new Action(DisplayAllEmailsSentMessage));
                }
            }, timer, 3000, Timeout.Infinite);

    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }

Обратите внимание, что вам придется использовать Invoke для взаимодействия с Windows Forms любым способом, например, для отображения окна сообщения. Это потому, что обратный вызов Threading.Timer выполняется в собственном потоке.

Возможно, вы также сможете использовать Windows.Forms.Timer, но я редко использую его сам, поскольку он находится в пространстве имен Windows.Forms и, следовательно, подходит только для пользовательского интерфейса, написанного на Windows Forms.

Я думаю, что вы определяете новую тему для этого процесса, потому что если вы пишете System.Threading.Thread.Sleep(3000); означает, что основной поток собирается спать на 3000 мс.

Итак, создайте вложенный поток для этого процесса, и после этого вы можете остановить / перевести ваш поток в поток.

Сервер Smtp разрывает ваше соединение из-за неактивности. Это наиболее вероятно, чтобы освободить ресурсы на сервере.

Из документации SmtpClient:

Соединение, установленное текущим экземпляром класса SmtpClient с SMTP-сервером, можно использовать повторно, если приложение желает отправить несколько сообщений на один и тот же SMTP-сервер. Это особенно полезно при использовании аутентификации или шифрования для установления соединения с SMTP-сервером. Процесс аутентификации и установления сеанса TLS может быть дорогостоящим процессом. Требование восстановления соединения для каждого сообщения при отправке большого количества сообщений на один и тот же SMTP-сервер может оказать существенное влияние на производительность.

В целом, другие респонденты правы, говоря, что вы не должны спать между отправкой. Сервер Smtp должен быть достаточно надежным, чтобы обрабатывать все электронные письма, которые вы можете отправить ему последовательно.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

 class MailSender
    {
        public static int CreateMessageMdp(String destination,String mdp)
        {
            try
            {
                var client = new SmtpClient("smtp.domain.com", 587)
                {
                    Credentials = new NetworkCredential("appgestionali@domain.com", "password"),
                    EnableSsl = true
                };
                DateTime localDate = DateTime.Now;
                string body = "Suite à votre demande de mot de passe le " + localDate.ToString("F") + "\n on vous envoi votre mot de passe est :" + mdp;
                client.Send("appgestionali@domain.com", destination, "Information", body);
            }
            catch (Exception ex)
            {
                MessageBox.Show(""+ ex.GetBaseException());
                return -1;
            }
            return 0;
        }
    }
}
Другие вопросы по тегам