1

I am doing a c# Winform application which automatically sends 2 types of e-mails :

The first group of mail must be sent only on Mondays (weekly), at 9am, the second group of email must be sent only the 1st day of every month (monthly).

Currently i'm doing this

if (day_event == "monday" && DateTime.Now.Hour.ToString() == heuresortiehebdo)
{
    //starting first group of mails
}                    
else if(DateTime.Now.Day==1 && DateTime.Now.Hour.ToString() == heuresortiemensuels)
{
     //starting 2nd group of mails
} 

(heuresortiehebdo and heuresortiemensuels are variables which are set from APP.config file, it is the hour set for sending each group of mails)

So this solution works for 1 time, but the goal is to let the application open and never stop it, send automatically mails when it's time and hour. I've thought about threads but how to check everytime if it is the good day and good hour ? Without using windows task scheduler.

stuartd
  • 70,509
  • 14
  • 132
  • 163
Alex
  • 863
  • 1
  • 9
  • 15
  • I think you should implement this inside a timer which runs all the time, and do those two every one hour – Antonios Tsimourtos Oct 27 '16 at 12:46
  • 4
    _"the goal is to let the application open and never stop it, send automatically mails when it's time and hour"_ - sounds more like a job for a service than a Winforms app. – stuartd Oct 27 '16 at 12:46
  • 1
    Possible duplicate of [How to set timer to execute at specific time in c#](http://stackoverflow.com/questions/21299214/how-to-set-timer-to-execute-at-specific-time-in-c-sharp) – Sinatr Oct 27 '16 at 12:46
  • 5
    Write these as separate programs and use the Windows task scheduler to do all the hard work for you. – ChrisF Oct 27 '16 at 12:47
  • _"Without using windows task scheduler"_. Why not? – 001 Oct 27 '16 at 12:48
  • @JohnnyMopp Because if I use the scheduler I will not be able to modify parameters in it (I write in textboxs mail adresses and it saves in the App.config file). This app is for users which can't enter the code to modify it. So if the app is always open, they can add parameters. If I use the scheduler, everytime I open a mail will be sent.. – Alex Oct 27 '16 at 13:09

3 Answers3

1

I would suggest to use Quartz for .NET library. It takes CRON expressions to create custom schedulers.

http://www.quartz-scheduler.net/documentation/index.html

This is CRON to be executed on every monday at 9 am:

0 0 9 ? * MON *

This is CRON to be executed on the first day of every month at mid day:

0 0 12 1 1/1 ? *

We can make CRON expressions here: http://www.cronmaker.com/

pergy
  • 5,285
  • 1
  • 22
  • 36
Vax
  • 343
  • 2
  • 15
0

You can do something like this. Here we are using a timer to do the scheduling part of the program. You can use this in a windows service to make your program more effective. But if that's not what you want, you can still use this in your winforms app.

public class EmailScheduler : IDisposable
{
    private readonly Timer clock;

    public EmailScheduler()
    {
        clock = new Timer();
        clock.Interval = 1000; // runs every second just like a normal clock            
    }       

    public void Start()
    {
        clock.Elapsed += Clock_Elapsed;
        this.clock.Start();
    }

    public void Stop()
    {
        clock.Elapsed -= Clock_Elapsed;
        this.clock.Stop();
    }

    private void Clock_Elapsed(object sender, ElapsedEventArgs e)
    {
        var now = DateTime.Now;

        // Here we check 9:00.000 to 9:00.999 AM. Because clock runs every 1000ms, it should run the schedule
        if (now.DayOfWeek == DayOfWeek.Monday && 
            (now.TimeOfDay >= new TimeSpan(0, 9, 0, 0, 0) && now.TimeOfDay <= new TimeSpan(0, 9, 0, 0, 999)))
        {
            // 9 AM schedule
        }

        if(now.Date.Day == 1 &&
            (now.TimeOfDay >= new TimeSpan(0, 9, 0, 0, 0) && now.TimeOfDay <= new TimeSpan(0, 9, 0, 0, 999)))
        {
            // 1 day of the month at 9AM
        }
    }

    public void Dispose()
    {
        if (this.clock != null)
        {
            this.clock.Dispose();
        }
    }
}

To start scheduler you may do something like this in your form.

   private EmailScheduler scheduler;
   public void FormLoad()
   {
       scheduler =  new EmailScheduler();
       scheduler.Start();
   }

   public void FormUnload()
   {
       scheduler.Stop();
       scheduler.Dispose();
   }
Kosala W
  • 2,133
  • 1
  • 15
  • 20
  • This solution sounds good but which function have I to call in my Form_Load() to get the scheduler start and do events? – Alex Oct 27 '16 at 14:02
  • Please see the updated answer. You will still have to implement your email sending function within the `if` condition of `Clock_Elapsed` event. Hope you have noticed that already. I would implement that as an `async` call. – Kosala W Oct 27 '16 at 22:42
0

Automate it using Windows Task Scheduler. If the application does one thing, for all of 30 seconds daily, there's no reason to tie up system resources and have it running constantly.

Now, you had issues about the managing the emails to be sent. There's a couple of options to resolve that.

Option 1 is to build a small front end that performs the necessary configuration options that are stored either in some shared config space or a database

Option 2 (and the one I would do) is to have the application start typically into an interface mode to allow for configuration work, and to manually send the emails. But also provide a parameter that can be passed in via the command line (or the parameters options of the scheduled task) which sends the email based on the last saved configuration or even a specific configuration if desired.

Stephen Wrighton
  • 36,783
  • 6
  • 67
  • 86