locked
Best practice for executing tasks repeatedly RRS feed

  • Question

  • User1864322503 posted

    In the past, my company creates ConsoleApplications and calls them from the Task Scheduler on our web server. While this approach has worked perfectly fine for us in the past, it's just another thing for us to maintain, and be responsible for. For an upcoming project, we will need to check (probably 1x weekly) for any users who still need to perform a task in our website - if they haven't submitted yet, then we will generate a reminder email to each & every user that still needs to close out the week.

    I was suggesting that we don't need to make a console application to do this. Really it is quite simple:

    1. Identify users that haven't submitted for the current week yet.
    2. For each user, execute an email reminder method
    3. Done...

    So pretty much I am looking for a good design for implementing this weekly task to run on my website.

    Friday, August 2, 2019 7:13 PM

Answers

  • User-1034726716 posted

    I am looking for a good design for implementing this weekly task to run on my website.

    Have you tried looking into Quartz.net? https://www.quartz-scheduler.net/

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, August 2, 2019 7:18 PM
  • User711641945 posted

    Hi nvielbig,

    Here is just a simple logic to advise you how to generate a reminder email for background task with hosted services:

     public class TimedHostedService: IEmailSender, IHostedService, IDisposable
        {
            private Timer _timer;
            private readonly BufferBlock<MailMessage> mailMessages;
            private readonly ILogger logger;
            private readonly SmtpClient smtpClient;
            private Task sendTask;
            private CancellationTokenSource cancellationTokenSource;
            public TimedHostedService(IConfiguration configuration, ILogger<TimedHostedService> logger)
            {
                this.logger = logger;
                this.mailMessages = new BufferBlock<MailMessage>();
                this.smtpClient = CreateSmtpClient(configuration);
            }
    
            public SmtpClient CreateSmtpClient(IConfiguration configuration)
            {
                //create your own smtpclient
            }
    
            public Task StartAsync(CancellationToken cancellationToken)
            {
                logger.LogInformation("Starting background task");
                //set the timer
                _timer = new Timer(DoWork, null,TimeSpan.Zero,TimeSpan.FromDays(7));
    cancellationTokenSource = new CancellationTokenSource();
    sendTask = Send(cancellationTokenSource.Token); return Task.CompletedTask; } private void DoWork(object state) { logger.LogInformation("Timed Background Service is working."); } public async Task StopAsync(CancellationToken cancellationToken) { _timer?.Change(Timeout.Infinite, 0);
    //cancel the e-mail delivery CancelSendTask(); //Next, we wait for sendTask to end, but no longer than what the web host allows await Task.WhenAny(sendTask, Task.Delay(Timeout.Infinite, cancellationToken)); } private void CancelSendTask() { logger.LogInformation("Stopping e-mail background delivery"); } //This public method will be used by other services (such as a Controller) to post messages to the email sender service. //They will be sent asynchronously in background public void Post(string subject, string body, string recipients, string sender) {
    //more logic... } public async Task Send(CancellationToken token) { logger.LogInformation("E-mail background delivery started"); while (!token.IsCancellationRequested) { MailMessage message = null; try { //If the token gets canceled, then we'll stop waiting //since an OperationCanceledException will be thrown message = await mailMessages.ReceiveAsync(token); //as soon as a message is available, we'll send it await smtpClient.SendMailAsync(message); logger.LogInformation($"E-mail sent to {message.To}"); } catch (OperationCanceledException) { //We need to terminate the delivery, so we'll just break the while loop break; } catch { logger.LogWarning($"Couldn't send an e-mail to {message.To}"); } } logger.LogInformation("E-mail background delivery stopped"); } public void Dispose() { CancelSendTask(); } }

    Reference :https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.2&tabs=visual-studio

    Best Regards,

    Rena

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, August 5, 2019 7:18 AM

All replies

  • User-1034726716 posted

    I am looking for a good design for implementing this weekly task to run on my website.

    Have you tried looking into Quartz.net? https://www.quartz-scheduler.net/

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, August 2, 2019 7:18 PM
  • User711641945 posted

    Hi nvielbig,

    Here is just a simple logic to advise you how to generate a reminder email for background task with hosted services:

     public class TimedHostedService: IEmailSender, IHostedService, IDisposable
        {
            private Timer _timer;
            private readonly BufferBlock<MailMessage> mailMessages;
            private readonly ILogger logger;
            private readonly SmtpClient smtpClient;
            private Task sendTask;
            private CancellationTokenSource cancellationTokenSource;
            public TimedHostedService(IConfiguration configuration, ILogger<TimedHostedService> logger)
            {
                this.logger = logger;
                this.mailMessages = new BufferBlock<MailMessage>();
                this.smtpClient = CreateSmtpClient(configuration);
            }
    
            public SmtpClient CreateSmtpClient(IConfiguration configuration)
            {
                //create your own smtpclient
            }
    
            public Task StartAsync(CancellationToken cancellationToken)
            {
                logger.LogInformation("Starting background task");
                //set the timer
                _timer = new Timer(DoWork, null,TimeSpan.Zero,TimeSpan.FromDays(7));
    cancellationTokenSource = new CancellationTokenSource();
    sendTask = Send(cancellationTokenSource.Token); return Task.CompletedTask; } private void DoWork(object state) { logger.LogInformation("Timed Background Service is working."); } public async Task StopAsync(CancellationToken cancellationToken) { _timer?.Change(Timeout.Infinite, 0);
    //cancel the e-mail delivery CancelSendTask(); //Next, we wait for sendTask to end, but no longer than what the web host allows await Task.WhenAny(sendTask, Task.Delay(Timeout.Infinite, cancellationToken)); } private void CancelSendTask() { logger.LogInformation("Stopping e-mail background delivery"); } //This public method will be used by other services (such as a Controller) to post messages to the email sender service. //They will be sent asynchronously in background public void Post(string subject, string body, string recipients, string sender) {
    //more logic... } public async Task Send(CancellationToken token) { logger.LogInformation("E-mail background delivery started"); while (!token.IsCancellationRequested) { MailMessage message = null; try { //If the token gets canceled, then we'll stop waiting //since an OperationCanceledException will be thrown message = await mailMessages.ReceiveAsync(token); //as soon as a message is available, we'll send it await smtpClient.SendMailAsync(message); logger.LogInformation($"E-mail sent to {message.To}"); } catch (OperationCanceledException) { //We need to terminate the delivery, so we'll just break the while loop break; } catch { logger.LogWarning($"Couldn't send an e-mail to {message.To}"); } } logger.LogInformation("E-mail background delivery stopped"); } public void Dispose() { CancelSendTask(); } }

    Reference :https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.2&tabs=visual-studio

    Best Regards,

    Rena

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, August 5, 2019 7:18 AM