I have a problem with a windows service.
protected override void OnStart(string[] args)
{
while (!File.Exists(#"C:\\Users\\john\\logOn\\oauth_url.txt"))
{
Thread.Sleep(1000);
}
...
I have to wait for a particular file, thus while loop is necessary, but the service will not be able to start with loop like this. What I can do to have a running service and a mechanism that checks if a file exists ?
The best option is to have a timer System.Timers.Timer in your service.
System.Timers.Timer timer = new System.Timers.Timer();
In the constructor add the handler for the Elapsed event:
timer.Interval = 1000; //miliseconds
timer.Elapsed += TimerTicked;
timer.AutoReset = true;
timer.Enabled = true;
Then in the OnStart method start that timer:
timer.Start();
In the event handler do your work:
private static void TimerTicked(Object source, ElapsedEventArgs e)
{
if (!File.Exists(#"C:\Users\john\logOn\oauth_url.txt"))
return;
//If the file exists do stuff, otherwise the timer will tick after another second.
}
A minimal service class will look somewhat like this:
public class FileCheckServivce : System.ServiceProcess.ServiceBase
{
System.Timers.Timer timer = new System.Timers.Timer(1000);
public FileCheckServivce()
{
timer.Elapsed += TimerTicked;
timer.AutoReset = true;
timer.Enabled = true;
}
protected override void OnStart(string[] args)
{
timer.Start();
}
private static void TimerTicked(Object source, ElapsedEventArgs e)
{
if (!File.Exists(#"C:\Users\john\logOn\oauth_url.txt"))
return;
//If the file exists do stuff, otherwise the timer will tick after another second.
}
}
I would consider using FileSystemWatcher as that is exactly what it is intended for, to monitor changes on the filesystem. Once event is raised on a folder, you can check if that particular file exists.
The default example in MSDN actually shows monitoring of .txt file https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx
I have a service written in C# (.NET 1.1) and want it to perform some cleanup actions at midnight every night. I have to keep all code contained within the service, so what's the easiest way to accomplish this? Use of Thread.Sleep() and checking for the time rolling over?
I wouldn't use Thread.Sleep(). Either use a scheduled task (as others have mentioned), or set up a timer inside your service, which fires periodically (every 10 minutes for example) and check if the date changed since the last run:
private Timer _timer;
private DateTime _lastRun = DateTime.Now.AddDays(-1);
protected override void OnStart(string[] args)
{
_timer = new Timer(10 * 60 * 1000); // every 10 minutes
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
_timer.Start();
//...
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// ignore the time, just compare the date
if (_lastRun.Date < DateTime.Now.Date)
{
// stop the timer while we are running the cleanup task
_timer.Stop();
//
// do cleanup stuff
//
_lastRun = DateTime.Now;
_timer.Start();
}
}
Check out Quartz.NET. You can use it within a Windows service. It allows you to run a job based on a configured schedule, and it even supports a simple "cron job" syntax. I've had a lot of success with it.
Here's a quick example of its usage:
// Instantiate the Quartz.NET scheduler
var schedulerFactory = new StdSchedulerFactory();
var scheduler = schedulerFactory.GetScheduler();
// Instantiate the JobDetail object passing in the type of your
// custom job class. Your class merely needs to implement a simple
// interface with a single method called "Execute".
var job = new JobDetail("job1", "group1", typeof(MyJobClass));
// Instantiate a trigger using the basic cron syntax.
// This tells it to run at 1AM every Monday - Friday.
var trigger = new CronTrigger(
"trigger1", "group1", "job1", "group1", "0 0 1 ? * MON-FRI");
// Add the job to the scheduler
scheduler.AddJob(job, true);
scheduler.ScheduleJob(trigger);
A daily task? Sounds like it should just be a scheduled task (control panel) - no need for a service here.
Does it have to be an actual service? Can you just use the built in scheduled tasks in the windows control panel.
The way I accomplish this is with a timer.
Run a server timer, have it check the Hour/Minute every 60 seconds.
If it's the right Hour/Minute, then run your process.
I actually have this abstracted out into a base class I call OnceADayRunner.
Let me clean up the code a bit and I'll post it here.
private void OnceADayRunnerTimer_Elapsed(object sender, ElapsedEventArgs e)
{
using (NDC.Push(GetType().Name))
{
try
{
log.DebugFormat("Checking if it's time to process at: {0}", e.SignalTime);
log.DebugFormat("IsTestMode: {0}", IsTestMode);
if ((e.SignalTime.Minute == MinuteToCheck && e.SignalTime.Hour == HourToCheck) || IsTestMode)
{
log.InfoFormat("Processing at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute);
OnceADayTimer.Enabled = false;
OnceADayMethod();
OnceADayTimer.Enabled = true;
IsTestMode = false;
}
else
{
log.DebugFormat("Not correct time at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute);
}
}
catch (Exception ex)
{
OnceADayTimer.Enabled = true;
log.Error(ex.ToString());
}
OnceADayTimer.Start();
}
}
The beef of the method is in the e.SignalTime.Minute/Hour check.
There are hooks in there for testing, etc. but this is what your elapsed timer could look like to make it all work.
As others already wrote, a timer is the best option in the scenario you described.
Depending on your exact requirements, checking the current time every minute may not be necessary.
If you do not need to perform the action exactly at midnight, but just within one hour after midnight, you can go for Martin's approach of only checking if the date has changed.
If the reason you want to perform your action at midnight is that you expect a low workload on your computer, better take care: The same assumption is often made by others, and suddenly you have 100 cleanup actions kicking off between 0:00 and 0:01 a.m.
In that case you should consider starting your cleanup at a different time. I usually do those things not at clock hour, but at half hours (1.30 a.m. being my personal preference)
I would suggest that you use a timer, but set it to check every 45 seconds, not minute. Otherwise you can run into situations where with heavy load, the check for a particular minute is missed, because between the time the timer triggers and the time your code runs and checks the current time, you might have missed the target minute.
You can also try the TaskSchedulerLibrary here http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8
Implement the abstract class AbstractScheduledTask and call the ScheduleUtilityFactory.AddScheduleTaskToBatch static method
For those that found the above solutions not working, it's because you may have a this inside your class, which implies an extension method which, as the error message says, only makes sense on a non-generic static class. Your class isn't static. This doesn't seem to be something that makes sense as an extension method, since it's acting on the instance in question, so remove the this.
Try this:
public partial class Service : ServiceBase
{
private Timer timer;
public Service()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
SetTimer();
}
private void SetTimer()
{
if (timer == null)
{
timer = new Timer();
timer.AutoReset = true;
timer.Interval = 60000 * Convert.ToDouble(ConfigurationManager.AppSettings["IntervalMinutes"]);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
}
private void timer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
//Do some thing logic here
}
protected override void OnStop()
{
// disposed all service objects
}
}
I would like for my service to be able to initiate communication with other services.
In order for it to act like a client and start the communication, I thought that an initialized in the constructor timer that calls a method every x seconds could be a good idea.
Is it a bad idea?
I can't see what could be wrong with this approach.
You could utilize System.Timers.Timer - https://msdn.microsoft.com/en-us/library/system.timers.timer%28v=vs.110%29.aspx
Set its Interval to value at which you want to raise Elapsed event of timer. Subscribe to Elapsed event using an event handler which you implement, in which you would communicate with the external service.
Edit: simple example
class Program
{
private static void timer_ElapsedEventHandler(object sender, EventArgs e)
{
// communicate to external service
Console.WriteLine("ElapsedEventHandler fired");
}
static void Main(string[] args)
{
var timer = new System.Timers.Timer();
timer.Interval = 3000;
timer.Elapsed += timer_ElapsedEventHandler;
timer.Start();
Console.WriteLine("Timer started");
Console.ReadLine();
}
}
In C#, the timer will trigger an event at a specific interval when enabled. How do I achieve this in Java?
I want to make a method to be run at a specific interval. I know how to do this in C#, but not Java.
Code in C#:
private void timer1_Tick(object sender, EventArgs e)
{
//the method
}
I tried Timer and TimerTask, but I am not sure whether the method will run when other methods are running.
You are looking at the right classes. The Timer and TimerTask are the right ones, and they will run in the background if you use them something like this:
TimerTask task = new RunMeTask();
Timer timer = new Timer();
timer.schedule(task, 1000, 60000);
One way is to use the ExecutorService:
Runnable task = new Runnable() {
#Override
public void run() {
// your code
}
};
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(task, initialDelay, period, TimeUnit.Seconds);
You can use the codeplex library to implement this.
Schedule a task to run every second with initial delay of 5 seconds
new Timer().Schedule(DoSomething, 5000, 1000);
Schedule a task to run everyday at 3 AM
new Timer().Schedule(DoSomething, Timer.GetFutureTime(3), Timer.MILLISECONDS_IN_A_DAY);
You can use javax.swing.Timer. It has delay in constructor:
Timer timer = new Timer(DELAY_IN_MILLISECONDS_INT, new ActionListener() {
public void actionPerformed(ActionEvent e) {
//some code here
}
});
Is there an analog to the following static function from the Qt library in Windows Forms?
http://doc.qt.io/qt-5/qtimer.html#singleShot
The best I can come up with is the following:
ThreadPool.QueueUserWorkItem((o) =>
{
Thread.Sleep(someNumberOfMilliseconds);
DoDelayedWorkHere();
});
UPDATE
This does the trick using System.Windows.Forms.Timer.
var timer = new System.Windows.Forms.Timer();
timer.Interval = someNumberOfMilliseconds;
timer.Tick += (o, args) =>
{
timer.Stop();
DoDelayedWorkHere();
};
timer.Start();
QTimer is a synchronous timer, just like the Winforms Timer. Threading or one of the other Timer classes is not a substitute. A single-shot is easy to implement, just set the timer's Enabled property to false in the Tick event handler. No danger of a race:
private void timer1_Tick(object sender, EventArgs e) {
((Timer)sender).Enabled = false;
// etc..
}
How about System.Threading.Timer? Use one of the constructors with the period parameter and specify the parameter accordingly.