Как подождать 24 часа перед завершением асинхронной задачи?

#c# #asp.net-mvc #delay

#c# #asp.net-mvc #задержка

Вопрос:

Я создаю приложение MVC с .NET Framework, и в одном из моих контроллеров я вызываю асинхронную задачу, которая отправляет электронное письмо подписанному пользователю.

Эта задача вызывается, когда пользователь нажимает определенный флажок, и электронное письмо предназначено для работы в качестве напоминания.

Вся задача работает по назначению (пользователь получает электронное письмо, когда установлен флажок), но мне нужно, чтобы оно подождало 24 часа, прежде чем отправлять электронное письмо, поскольку это напоминание.

В настоящее время электронное письмо отправляется сразу, как я могу отложить завершение моей «задачи электронной почты», пока код продолжается?

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

1. Quartz.NET к решению!

2. Вы могли бы сохранить электронное письмо, а затем запускать отдельное задание (каждые несколько минут) для проверки отправки электронных писем

3. ^^ Это. Не начинайте 24-часовое ожидание, а затем отправляйте электронное письмо. Представьте, что у вас 500 из них в очереди, и сервер перезапущен, потому что Windows. Все они будут потеряны.

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

5. Приложение (и почтовая задача) не будут использоваться ежедневно, возможно, один или два раза в неделю. Я полагаю, что максимальное количество электронных писем в очереди равно двум. Возможна ли простая задержка? Или вы все равно сохранили бы электронные письма?

Ответ №1:

Используйте библиотеку, подобную Hangfire, которая позволяет планировать фоновые задания и сохранять их в постоянном хранилище.

Затем вы можете легко запланировать задание, например:

 BackgroundJob.Schedule(
    () => SendEmail("user@domain"),
    TimeSpan.FromDays(1));
  

Ответ №2:

Это классическая проблема X Y. Хотя может быть возможно заставить вашу систему ждать 24 часа, вы создаете очень хрупкую систему, на которую могут повлиять сброс пула приложений и перезагрузка сервера.

Оставляя в стороне возможность неожиданной перезагрузки, что произойдет, когда завершится цикл обслуживания и произойдет запланированная перезагрузка? Сколько у вас будет напоминаний по электронной почте в очереди, с которыми вы ничего не сможете сделать?

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

За эти годы я использовал МНОЖЕСТВО систем отправки электронной почты, и даже для немедленной отправки мы использовали посредника базы данных с одной специальной службой отправки электронной почты Windows для создания и отправки фактического электронного письма. Централизовав процесс создания электронной почты, вы не только получаете одно место для хранения кода отправки электронной почты, но и можете повысить надежность всей системы.

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

Ответ №3:

Пусть задача подождет 24 часа перед отправкой почты.

      await Task.delay(TimeSpan.FromHours(24));
  

Добавьте эту строку в свою асинхронную функцию перед отправкой электронного письма

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

1. В качестве альтернативы можно использовать Task.Delay(TimeSpan.FromDays(1)) или Task.Delay(TimeSpan.FromHours(24))

2. На самом деле, использование Task.Delay в этом сценарии является хрупким. Предположим, что ваше приложение вышло из строя (или убито), и все ваши напоминания будут потеряны.

3. @hal 1 если он работает в IIS, максимальное время ожидания запроса не сможет быть установлено достаточно высоким для успешного выполнения. Не говоря уже о сбросе пула приложений.