Execute action every day at the same time in C #

2

I am working on a Console application that must perform some actions at certain times of the day (I clarify that it is not a service because I need the execution of processes)

The issue is that I must start an application at a certain time and close it in another.

Searching, I found a SO answer in English that does something similar to what I'm looking for but with a single execution, I tried to modify the snippet a bit in the following way:

    private void SetUpTimer(TimeSpan alertTime, DateTime current, Action<TimeSpan> delg)
    {            

        TimeSpan timeToGo = alertTime - current.TimeOfDay;

        if (timeToGo < TimeSpan.Zero)
        { 
            return;//time already passed
        }
        this.timer = new System.Threading.Timer(x =>
        {
            delg(alertTime);
        }, null, timeToGo, Timeout.InfiniteTimeSpan);
    }

    public void OpenProcess(TimeSpan alertTime)
    {
        Console.WriteLine("Ejecutado {0}",DateTime.Now);            
        SetUpTimer(alertTime, DateTime.Now.AddDays(1), OpenProcess);
    }

and then I call it like this

SetUpTimer(new TimeSpan(13, 44, 00), DateTime.Now, OpenProcess);

The first round is done correctly, but the second time, the OpenProcess () function is not executed

Where is my error?

Thank you!

    
asked by Juan Salvador Portugal 12.11.2018 в 17:51
source

2 answers

5

In your code timeToGo marks the time remaining for your timer to run again and is defined as a subtraction of a TimeStamp ( alertTime ) from another ( current.TimeOfDay ).

What happens when you call SetUpTimer(alertTime, DateTime.Now.AddDays(1), OpenProcess); from OpenProcess ?

That you use AddDays is irrelevant, since to calculate the time you use TimeOfDay that does not take into account the date, and you also call it at the same time that the tick of the timer is supposed to jump, with what actually timeToGo gives a negative result, and logically will not fire again the next day.

I have already told you in a comment that it is better in my opinion to use a scheduled windows task for these tasks, but I give you a solution if you insist on this path.

The solution is to use dates instead of TimeStamps to calculate the time remaining to re-trigger the timer tick, something like this:

private void SetUpTimer(Datetime alertTime, Action<TimeSpan> delg)
{            

    TimeSpan timeToGo = alertTime - DateTime.Now;
    ...
}

To call it the first time, like this (if it is before the time at which you program it):

DateTime fechaProxEjecución = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 13, 44, 0);
SetUpTimer(fechaProxEjecución,OpenProcess);

And OpenProcess would be like this:

public void OpenProcess(TimeSpan alertTime)
{
    Console.WriteLine("Ejecutado {0}",DateTime.Now);            
    DateTime fechaProxEjecución = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day+1, 13, 44, 0);
    SetUpTimer(fechaProxEjecución,OpenProcess);
}
    
answered by 12.11.2018 / 18:20
source
3

I think the best way to do this is to implement the concept of Workers. You must make your Console application execute the required action instantly, without checking schedules or dates, and then schedule a recurring task through the operating system. In the case of Microsoft Windows you can use Task Scheduler - Create a Basic Task - Declare how often the task will be executed - Action = Start a program, you look for the Console and Ready application.

    
answered by 12.11.2018 в 18:41