Асинхронная отправка писем в C #?

Я разрабатываю приложение, в котором пользователь нажимает / нажимает кнопку ввода на определенной кнопке в окне, приложение выполняет некоторые проверки и определяет, отправлять ли пару писем или нет, а затем показывать другое окно с сообщением.

Моя проблема заключается в том, что отправка двух писем замедляет процесс заметно, а для некоторых (~ 8) секунд первое окно выглядит замороженным во время отправки.

Есть ли способ отправить эти письма на задний план и сразу отобразить следующее окно?

Пожалуйста, не ограничивайте свой ответ «используйте X-class» или «просто используйте метод X», поскольку я еще не слишком хорошо знаком с языком, и вам будет по достоинству оценена еще одна информация.

Благодарю.

Начиная с .NET 4.5 SmtpClient реализует asynchronous ожидаемый метод SendMailAsync . В результате для асинхронного посылки электронной почты:

 public async Task SendEmail(string toEmailAddress, string emailSubject, string emailMessage) { var message = new MailMessage(); message.To.Add(toEmailAddress); message.Subject = emailSubject; message.Body = emailMessage; using (var smtpClient = new SmtpClient()) { await smtpClient.SendMailAsync(message); } } 

Поскольку это небольшая единица работы, вы должны использовать ThreadPool.QueueUserWorkItem для аспекта Threading. Если вы используете class SmtpClient для отправки своей почты, вы можете обработать событие SendCompleted, чтобы дать отзыв пользователю.

 ThreadPool.QueueUserWorkItem(t => { SmtpClient client = new SmtpClient("MyMailServer"); MailAddress from = new MailAddress("[email protected]", "My Name", System.Text.Encoding.UTF8); MailAddress to = new MailAddress("[email protected]"); MailMessage message = new MailMessage(from, to); message.Body = "The message I want to send."; message.BodyEncoding = System.Text.Encoding.UTF8; message.Subject = "The subject of the email"; message.SubjectEncoding = System.Text.Encoding.UTF8; // Set the method that is called back when the send operation ends. client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); // The userState can be any object that allows your callback // method to identify this send operation. // For this example, I am passing the message itself client.SendAsync(message, message); }); private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e) { // Get the message we sent MailMessage msg = (MailMessage)e.UserState; if (e.Cancelled) { // prompt user with "send cancelled" message } if (e.Error != null) { // prompt user with error message } else { // prompt user with message sent! // as we have the message object we can also display who the message // was sent to etc } // finally dispose of the message if (msg != null) msg.Dispose(); } 

Создавая новый SMTP-клиент каждый раз, это позволит вам отправлять электронные письма одновременно.

Не слишком сложно просто отправить сообщение в отдельный stream:

 using System.Net.Mail; Smtp.SendAsync(message); 

Или, если вы хотите построить целое сообщение в отдельном streamе, а не просто отправить его асинхронно:

 using System.Threading; using System.Net.Mail; var sendMailThread = new Thread(() => { var message=new MailMessage(); message.From="from e-mail"; message.To="to e-mail"; message.Subject="Message Subject"; message.Body="Message Body"; SmtpMail.SmtpServer="SMTP Server Address"; SmtpMail.Send(message); }); sendMailThread.Start(); 

Метод SmtpClient.SendAsync

Образец

 using System; using System.Net; using System.Net.Mail; using System.Net.Mime; using System.Threading; using System.ComponentModel; namespace Examples.SmptExamples.Async { public class SimpleAsynchronousExample { static bool mailSent = false; private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e) { // Get the unique identifier for this asynchronous operation. String token = (string) e.UserState; if (e.Cancelled) { Console.WriteLine("[{0}] Send canceled.", token); } if (e.Error != null) { Console.WriteLine("[{0}] {1}", token, e.Error.ToString()); } else { Console.WriteLine("Message sent."); } mailSent = true; } public static void Main(string[] args) { // Command line argument must the the SMTP host. SmtpClient client = new SmtpClient(args[0]); // Specify the e-mail sender. // Create a mailing address that includes a UTF8 character // in the display name. MailAddress from = new MailAddress("[email protected]", "Jane " + (char)0xD8+ " Clayton", System.Text.Encoding.UTF8); // Set destinations for the e-mail message. MailAddress to = new MailAddress("[email protected]"); // Specify the message content. MailMessage message = new MailMessage(from, to); message.Body = "This is a test e-mail message sent by an application. "; // Include some non-ASCII characters in body and subject. string someArrows = new string(new char[] {'\u2190', '\u2191', '\u2192', '\u2193'}); message.Body += Environment.NewLine + someArrows; message.BodyEncoding = System.Text.Encoding.UTF8; message.Subject = "test message 1" + someArrows; message.SubjectEncoding = System.Text.Encoding.UTF8; // Set the method that is called back when the send operation ends. client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); // The userState can be any object that allows your callback // method to identify this send operation. // For this example, the userToken is a string constant. string userState = "test message1"; client.SendAsync(message, userState); Console.WriteLine("Sending message... press c to cancel mail. Press any other key to exit."); string answer = Console.ReadLine(); // If the user canceled the send, and mail hasn't been sent yet, // then cancel the pending operation. if (answer.StartsWith("c") && mailSent == false) { client.SendAsyncCancel(); } // Clean up. message.Dispose(); Console.WriteLine("Goodbye."); } } } 

Просто потому, что это немного расплывчато … Я буду кратким …

Существует много способов сделать асинхронную или параллельную работу в c # /. Net и т. Д.

Самый быстрый способ сделать то, что вы хотите, – использовать stream рабочего фона, который позволит избежать блокировки вашего пользовательского интерфейса.

Совет с фоновыми рабочими streamами: вы не можете напрямую обновлять пользовательский интерфейс от них (сходство streamов и Marshalling – это то, чему вы научились справляться …)

Другое дело, чтобы рассмотреть … если вы используете стандартный материал System.Net.Mail для отправки писем … будьте осторожны, как вы создаете свою логику. Если вы изолируете все это в каком-то методе и вызывают его снова и снова, ему, вероятно, придется каждый раз сбрасывать и перестраивать соединение с почтовым сервером, а латентность, связанная с аутентификацией и т. Д., Все равно замедлит все это без необходимости. При необходимости отправьте несколько электронных писем через одно открытое соединение с почтовым сервером.

Ниже приведен пример пожара и забывания с помощью async с использованием .Net 4.5.2+:

 BackgroundTaskRunner.FireAndForgetTaskAsync(async () => { SmtpClient smtpClient = new SmtpClient(); // using configuration file settings MailMessage message = new MailMessage(); // TODO: Initialize appropriately await smtpClient.SendMailAsync(message); }); 

где BackgroundTaskRunner:

 public static class BackgroundTaskRunner { public static void FireAndForgetTask(Action action) { HostingEnvironment.QueueBackgroundWorkItem(cancellationToken => // .Net 4.5.2+ required { try { action(); } catch (Exception e) { // TODO: handle exception } }); } ///  /// Using async ///  public static void FireAndForgetTaskAsync(Func action) { HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => // .Net 4.5.2+ required { try { await action(); } catch (Exception e) { // TODO: handle exception } }); } } 

Работает как очарование Azure App Services.

Попробуй это:

 var client = new System.Net.Mail.SmtpClient("smtp.server"); var message = new System.Net.Mail.MailMessage() { /* provide its properties */ }; client.SendAsync(message, null); 

Используйте class SmtpClient и используйте метод SendAsync в пространстве имен System.Net.Mail.

То, что вы хотите сделать, – запустить задачу электронной почты в отдельном streamе, чтобы основной код мог продолжить обработку, в то время как другой stream выполняет работу по электронной почте.

Вот учебник о том, как это сделать: Threading Tutorial C #

Самое простое решение – создать BackgroundWorker и направить почту в очередь. Затем просто позвольте BackgroundWorker пройти очередь и отправить каждую почту.

См. Также Как выполнить операцию в фоновом режиме

Используя параллельную библиотеку задач в .NET 4.0, вы можете:

 Parllel.Invoke(() => { YourSendMailMethod(); }); 

Также см. Сообщение в блоге cristina manu о Parallel.Invoke () против явного управления задачами.

  • Как отправить почту из приложения iPhone
  • Mail multipart / alternative vs multipart / mixed
  • В чем разница между Sender, From и Return-Path?
  • Давайте будем гением компьютера.