where should i put the code in C# service - c#

I wrote little service that check some folder every minute and send the content to FTP folder. inside the service in OnStart method i sets timer for event that runs every minute:
protected override void OnStart(string[] args)
{
aTimer = new Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 60000;
aTimer.Enabled = true;
}
The Event:
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
some logic here....
}
Now my question: is that ok to invoke onStart method only once and let the event do the rest? or should i run onStart method every minute instead of event?

Your application logic which runs every minute, should be inside the event OnTimedEvent.
Read more in Microsoft Documentation here which gives a walkthrough on how to create a Windows Service Application: MS Docs - Walkthrough: Create a Windows service app
is that ok to invoke onStart method only once and let the event do the rest?
Yes, OnStart should be executed only once, which is when your service is started.
or should i run onStart method every minute instead of event?
No, OnStart should run only once.
Suggestion: You might want to increase the time interval, if you are expecting a lot of files or if the file size is going to be large.

Related

scheduling a windows service without using the task scheduler

I have a windows service that archives files from a paticular folder. I want the program to run everday at a specific time. I can do that using the task scheduler. what I want to do is to schedule the task without actually assessing the windows task scheduler GUI. Maybe a batch script that schedules the program to run every day even when the system is on sleep or maybe something else i can do?
does anyone have an idea of how this thing can be implemented?
The solution is pretty basic . so the thing is that instead of using the task scheduler we are creating a scheduler itself in our code so there is a thread that will be created that will always be checking for the time that I want my actual code to run and once the current time is the time that I want the method to run it will trigger the main program(in the example the method I want to trigger is named ArchiveFile) .
so first in the OnStart I am setting a new timer and want it to fire 24x7,every hour.
then in the timer_elapse i want to check if the current time is the time I want my method to execute and if true it will call the method that I want to execute.(in this example I have set the time to be 9 pm or 21 hours)
protected override void OnStart(string[] args)
{
timer = new System.Timers.Timer();
timer.Interval = 36000; // that fires every hour
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); //calling the elapse event when the timer elapses
timer.AutoReset = true; // AutoReset is set to true as we want the timer to fire 24x7 so that the elapse event is executed only at the requried time
timer.Enabled = true;
}
protected void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) //everytime the elapse event occurs the TimeCheck method will be called
{
TimeCheck();
}
public void TimeCheck() //method to check if the current time is the time we want the archiving to occur
{
var dt = DateTime.Now.Hour;
if(dt==21)
{
Archivefile();
}
}

C# Timer elapsed one instance at a time

I am creating windows service. I want to run the service every 30 seconds.
So I have used timer on windows service start using the following code.
protected override void OnStart(string[] args)
{
timer1 = new Timer();
timer1.Interval = 30000;
timer1.Elapsed += new ElapsedEventHandler(timer1_tick);
timer1.Start();
}
In timer1_tick function, I am performing some actions like updating user details, uploading and downloading files.
But here I am not sure that the above action will finish within 30 seconds.
So I want to run one at a time.
Here timer1_tick function called every exact 30 seconds. This should be happen only if the timer1_tick function finishes every task.
How to do that?
You should stop the timer and wait for the uploading and downloading of files to finish using Timer.Stop(); and Timer.Start():
void timer1_tick(...){
timer1.Stop();
//Do your download, upload, etc.
timer1.Start();
}
Hope it helps!
As per your requirement use Asynchronous Programming. It might be help you. Thank You
timer1.Elapsed += new ElapsedEventHandler(await timer1_tick);
async Task<void> timer1_tick()
{
//Do your download, upload, etc.
}

Problems starting a .NET Windows Service when using Thread.Sleep

I have created a .NET Windows Service and installed the debug release from the bin/debug folder (yes I know this isn't a good approach, but I just want to be able to test it and attach debugger).
The service basically runs in an endless loop checking an FTP directory for files, processing them, sleeping for a minute and then looping.
When I attempt to start the service I get the following error
Error 1053: The service did not respond to the start or control request in a timely fashion
On further inspection the service is completing the first loop and then timing out during the first thread sleep. As such I'm somewhat confused as to how I should start the service. Is it my (lack of) understanding of threading that is causing this?
My start code is
protected override void OnStart(string[] args)
{
eventLog.WriteEntry("Service started");
ThreadStart ts = new ThreadStart(ProcessFiles);
workerThread = new Thread(ts);
workerThread.Start();
}
In the ProcessFiles function, once a loop has been completed I simply have
eventLog.WriteEntry("ProcessFiles Loop complete");
Thread.Sleep(new TimeSpan(0,1,0));
When I check the event logs the 'ProcessFiles Loop complete' log is there, but that is the last event before the service timesout and fails to start.
Can someone explain what I am doing wrong?
EDIT
The way I am handling the loop in my ProcessFiles function is as below
while (!this.serviceStopped)
{
// Do Stuff
eventLog.WriteEntry("ProcessFiles Loop complete");
Thread.Sleep(new TimeSpan(0,1,0));
}
Cheers
Stewart
When I check the event logs the 'ProcessFiles Loop complete' log is there...
You might be having a code for file processing that does not return until the service gets timeout. You are trying to perform some task after interval, you better use System.Timers.Timer or System.Windows.Forms.Timer instead of loop to repeatedly perform some task.
To test if it is loop problem to can restrict loop to single iteration with sleep statement and check if service gets started.
protected override void OnStart(string[] args)
{
aTimer = new System.Timers.Timer(10000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 60000;
aTimer.Enabled = true;
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
aTimer.Enabled = false;
// Put file processing code here.
aTimer.Enabled = true;
}
Doh. I just realised I had the following code in my Main Program method that I was using to be able to debug in VS. Obviously then when I installed the debug release it was putting an infinite timeout on the main thread. Removing the debug code fixed the issue.
#if DEBUG
AdvanceLinkService myService = new AdvanceLinkService();
myService.OnDebug();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new AdvanceLinkService()
};
ServiceBase.Run(ServicesToRun);
#endif

How to make async pause in C#?

I have a program written in C# (Visual Studio), that works on a tray.
I want it to do one action every 10 minutes.
I have following code now:
while(true)
{
Thread.Sleep(10000);
// my stuff
}
But it doesn't work. It freezes a program.
You should use the timer object and not create a while loop.
System.Timers.Timer _timer = new System.Timers.Timer();
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
//30 seconds
_timer.Interval = 30000;
_timer.Start();
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
//do your logic
}
Thread.Sleep makes the calling thead Sleep for an X ammount of time. If this thread is the frontend thread (the one responsible for handling messages), it will indeed freeze the application since any message for handling events or repainting wont be handeled untill the Thread wakes up again and gets a chance of handling the messages.
What you should do is schedule this logic every 10 seconds.
Drop a timer on your form and specify it to run each 10 seconds. Within the Tick event, call your custom action.
Thread.Sleep "stops" the current thread. if you only have one thread, everything is paused.
What do you want to achieve ?
Perhaps you need a second thread, or perhaps the better solution a timer which triggers a action every 10 minutes
s. Task.StartNew() or ThreadPool

System.Timers.Timer delay hangs application

I have an issue with the System.Timers.Timer object. I use the timer object to perform a task at regular intervals. In the timer constructor I call the method doing the work ( DoTimeCheck() ), to ensure that the task is run once at startup also. The work (at regular intervals) is done in a BackgroundWorker.
I call the timer with this:
UpdaterTimer ut = UpdaterTimer.UpdaterTimerInstance;
My problem is that I need to delay the first run of the task with 3 minutes(the one that runs at application startup). Subsequent runs (Elapsed event) should run without delay. I thought of doing this by calling
System.Threading.Thread.Sleep(TimeToDelayFirstRunInMiliseconds);
but this fails, because it also hangs the UI of the app (main thread) making it unusable. How can I delay the first run of DoTimeCheck() without hanging the UI?
The code of the timer is below. If the issue is not presented in a clear manner please let me know and I will edit. Thank you in advance.
public sealed class UpdaterTimer : Timer
{
private static readonly UpdaterTimer _timer = new UpdaterTimer();
public static UpdaterTimer UpdaterTimerInstance
{
get { return _timer; }
}
static UpdaterTimer()
{
_timer.AutoReset = true;
_timer.Interval = Utils.TimeBetweenChecksInMiliseconds;
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Start();
DoTimeCheck();
}
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
DoTimeCheck();
}
private static void DoTimeCheck()
{
//... work here
}
}
One way of doing this would be to give the Timer Interval an initial value (e.g. 3 minutes). Then, in your Elapsed event handler, you could change the interval to your regular value which will be used from then on.
_timer.Interval = Utils.InitialCheckInterval;
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (_timer.Interval == Utils.InitialCheckInterval)
{
_timer.Interval = Utils.RegularCheckInterval;
}
DoTimeCheck();
}
It appears (although you've not shown that code) that you're calling Sleep(TimeToDelayFirstRunInMiliseconds); on the main/GUI thread, so that's what's causing your UI thread to hang. Instead, you should set your timer to be delayed by 3 minutes on the first run, then once it runs you change the timer again to run at the frequency you desire for all the subsequent runs.
Your UI resides on the same thread, so when you put the thread to sleep, it will cause your UI to hang as well. You need to run the timer on a different thread.
You're already using timers fine it seems. Just use another one to do a three minute delay before you start up your other timer.
timer = new Timer();
timer.AutoReset = false;
timer.Interval = 3*60*1000;
timer.Elapsed += startOtherTimerMethod;
timer.Start();
Edit: I should note that this is much the same as Peter Kelly's answer except that his solution is more elegant since it uses just one timer, no extra methods and takes advantage of the fact that the timer is changeable between runs. If you liked this answer, you'll love his. ;-)
Your UI needs a seperate thread, currently you are also sleeping the UI. Check this post.
You should not use thread.sleep in this situation you should use the winforms control
BackgroundWorker which never locks the main UI. You can write your logic there.
example here:
http://www.knowdotnet.com/articles/backgroundworker.html
Use a System.Threading.Timer - the constructor takes a parameter for the delay of the first run and an interval for the subsequent runs.

Categories