Отправка нескольких электронных писем асинхронно в быстрой последовательности

#c# #email #asp.net-core #asynchronous

#c# #Адрес электронной почты #asp.net-core #асинхронный

Вопрос:

Я разрабатываю веб-приложение с ASP.NET Core MVC 3.1, с использованием Visual Studio 2019 Community Edition, версия 16.8.0 (обновлено 11.11.2020).

В этом приложении администратор может вводить пользователей в базу данных. Всякий раз, когда вводится пользователь, этому пользователю отправляется сообщение электронной почты в фоновом режиме. Чтобы предотвратить задержку отображения страницы подтверждения, сообщение электронной почты отправляется асинхронно. Это работает нормально, за исключением случаев, когда администратор вводит несколько пользователей в быстрой последовательности. Тогда отправляется только одно или два сообщения, поскольку почтовый сервер накладывает ограничение на количество потоков, которые могут использоваться одновременно.

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

Вот некоторые сведения о моем текущем коде:

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

Функция вставки имеет следующий шаблон:

     void InsertUser(...)
    {
        // Insertion code here
    
        // If operation successful:
        Task t = SendGreetingsAsync(...);
    }
  

Как вы можете видеть, InsertUser(…) не «ожидает» отправки greetingsasync(…) . Если бы это произошло, преимущество асинхронности было бы потеряно. По крайней мере, так я понимаю.

SendGreetingsAsync(…) вызывает функцию SendGreetings(…) следующим образом:

     async Task SendGreetingsAsync(...)
    {
        await Task.Delay(1);
        SendGreetings(...);
    }
  

SendGreetings(…) — это синхронная функция по следующему шаблону:

     void SendGreetings(...)
    {
        // Send an e-mail to the user specified in the parameter list
    }
  

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

Любая помощь будет принята с благодарностью!

Комментарии:

1. Если вы отправляете электронные письма — вам нужно где-то их сохранить, чтобы иметь возможность повторить попытку. Существуют абсолютно веские причины, по которым SMTP-сервер временно отклоняет ваше электронное письмо, помимо той, с которой вы столкнулись, и в этом случае вам придется повторить попытку позже. Или вы можете использовать соответствующий SMTP-сервер, который сделает это за вас. Отправка электронных писем из веб-приложения способом «запустить и забыть» очень ненадежна.

2. Спасибо за этот совет и за столь быстрый ответ. Не могли бы вы объяснить, как «использовать правильный SMTP-сервер, который делает это за вас»?

Ответ №1:

Используйте SemaphoreSlim для ограничения параллелизма через путь кода.

 async Task SendGreetingsAsync(...)
{
    try 
    {
      await semaphore.WaitAsync();
      SendGreetings(...);
    }
    finally
    {
      semaphore.Release();
    }
}
  

Или добавьте электронные письма в BlockingCollection и попросите один фоновый поток отправить все электронные письма.

Комментарии:

1. Большое тебе спасибо, Дэвид. Я прочитаю об этих инструментах, о которых я никогда раньше не слышал.