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
Related
I have an application that calls static methods in a DLL every 60 seconds as part of a system "self-check" application. When I manually run the methods, they all complete in less than 10 seconds. My problem is the timer.elapsed event is firing twice, one right after the other. To add to that, for each time the timer elapses, the event fires one more time. (e.g. first time it's 2 firings, second it's 3, third it's 4, etc.) I have tried setting the timer.AutoReset = false along with setting timer.Enabled = false at the beginning of the elapsed event and then setting it to true at the end of the event. I've tried resetting the interval in the event. Every post I have found indicates that the above actions should have resolved this problem. Can anyone help me find what I'm missing?
static Timer cycle = new Timer();
static int cycCount = 0;
static void Main(string[] args)
{
Console.WriteLine("Firebird Survivor Auto Cycle Started.");
Console.CancelKeyPress += Console_CancelKeyPress;
cycle.Interval = 60000; //set interval for service checks.
cycle.Elapsed += new ElapsedEventHandler(CycleComplete_Elapsed);
cycle.AutoReset = false;
cycle.Enabled = true;
cycle.Elapsed += CycleComplete_Elapsed;
while (1 == 1) //stop main method from completing indefinitely
{
//WAIT FOR TIMER TO ELAPSE
}
}
private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
cycle = null;
}
static void CycleComplete_Elapsed(object sender, ElapsedEventArgs e) //method triggered by timer
{
cycle.Enabled = false;
cycCount++;
WormholeServiceControls.CheckWormHoleStatus();
TimeControls.CheckTimePl(); //call time check
PegasusServiceControls.CheckPegasusStatus(null);
Console.Clear();
Console.WriteLine("--------------------------");
Console.WriteLine(String.Format("| Successful Cycles: {0} |", cycCount));
Console.WriteLine("--------------------------");
cycle.Enabled = true;
}
It seems your problem comes from the event handling you are doing. You are assigning the Elapsed event more than one time:
cycle.Elapsed += new ElapsedEventHandler(CycleComplete_Elapsed);
cycle.Elapsed += CycleComplete_Elapsed;
Why this two lines?. You will be all right with only this:
cycle.Elapsed += new ElapsedEventHandler(CycleComplete_Elapsed);
Here is the scenario I'm trying to achieve,
My program has a timer which its interval is set to 10 seconds (10000ms).
I want to check for a specific conditions, for example if a specific file exists or has changed, then change timer.interval accordingly.
Here's my code:
static void Main(string[] args)
{
timer.Interval =10000;
timer.Elapsed += new System.Timers.ElapsedEventHandler(WriteToConsole);
timer.Start();
if(fileExists(#"C:\temp\1.txt"))
{
timer.Interval =20000; //20 seconds
}
else if(fileExists(#"C:\temp\2.txt"))
{
timer.Interval =15000; // 15 seconds
}
}
public static void WriteToConsole(object sender, System.Timers.ElapsedEventArgs args)
{
Console.WriteLine(DateTime.UtcNow);
}
But it doesn't work as I need it to.
I've already read these but couldn't find the solution.
1-2-3
Try writing your start after you specify your interval, or else stop the timer and start again later.
now I have a C# application, which runs 24/7 with a timer, which elapse all 30 seconds and do anything.
I want to make this application to a windows service, to run in the background. But the service crash immediately..
My code:
public static System.Timers.Timer _timer = new System.Timers.Timer();
static void Main(string[] args)
{
_timer.Interval = 30000;
_timer.Elapsed += timerCallback;
_timer.AutoReset = true;
_timer.Start();
}
public static void timerCallback(Object sender, System.Timers.ElapsedEventArgs e)
{
// Do anything..
}
And the error:
Windows could not start the Application service on Local Computer.
Error 1053: The service did not respond to the start or control request in a timely fashion
In the windows event viewer this message occured:
A timeout was reached (30000 milliseconds) while waiting for the Application service to connect.
But the error appear faster than 30 seconds?!
Any solutions to run the service??
Thanks
Michael
You could use a Timer to execute the logic periodically within windows service,
protected override void OnStart(string[] args)
{
base.OnStart(args);
Timer timer = new Timer();
timer.Interval = 30*1000;
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
timer.Start();
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
//put logic here that needs to be executed for every 30sec
}
I wonder how i can force my window service to restart or stop if it's running for already about 30 mins.
it's like:
if(service.runs == 30 mins){
service.stop()
or
service.restart()
}
by the way, I am using C# on this. And I am using a Thread here.
This is how my OnStart looks like:
Thread myThread;
protected override void OnStart(string[] args){
myThread = new Thread(new ThreadStart(this.myThreadFunction));
myThreadFunction.Start();
}
Please help.
Thanks
You need to run timer on service start. And set its elapsed event to 30 mins. If it is elapsed then you can apply your above check of stopping it. You also need to Reset your timer when ever the service is stopped/restarted.
//somewhere in your class
System.Timer.Timer tmr = new System.Timers.Timer();
//on construct or start event
tmr.Interval = 1800000; //30 minutes = 60*1000*30
tmr.Elapsed -= new ElapsedEventHandler(OnTimedEvent);
tmr.Elapsed += new ElapsedEventHandler(OnTimedEvent);
tmr.Start();
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
tmr.Stop();
ServiceController service = new ServiceController(yourserviceName);
service.Stop();
// service.Start() uncomment this line if your want to restart
}
protected override void OnStop()
{
}
I have a timer that needs to not process its elapsed event handler at the same time. But processing one Elapsed event may interfere with others. I implemented the below solution, but something feels wrong; it seems like either I should be using the timer differently or using another object within the threading space. The timer seemed to fit best because I do need to periodically check for a status, but sometimes checking will take longer than my interval. Is this the best way to approach this?
// member variable
private static readonly object timerLock = new object();
private bool found = false;
// elsewhere
timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
timer.Elapsed = Timer_OnElapsed;
timer.Start();
public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
{
lock(timerLock)
{
if (!found)
{
found = LookForItWhichMightTakeALongTime();
}
}
}
You could set AutoReset to false, then explicitly reset the timer after you are done handling it. Of course, how you handle it really depends on how you expect the timer to operate. Doing it this way would allow your timer to drift away from the actual specified interval (as would stopping and restarting). Your mechanism would allow each interval to fire and be handled but it may result in a backlog of unhandled events that are handled now where near the expiration of the timer that cause the handler to be invoked.
timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds;
timer.Elapsed += Timer_OnElapsed;
timer.AutoReset = false;
timer.Start();
public void Timer_OnElapsed(object sender, ElapsedEventArgs e)
{
if (!found)
{
found = LookForItWhichMightTakeALongTime();
}
timer.Start();
}
I usually stop the timer while processing it, enter a try/finally block, and resume the timer when done.
If LookForItWhichMightTakeALongTime() is going to take a long time, I would suggest not using a System.Windows.Forms.Timer because doing so will lock up your UI thread and the user may kill your application thinking that it has frozen.
What you could use is a BackgroundWorker (along with a Timer if so desired).
public class MyForm : Form
{
private BackgroundWorker backgroundWorker = new BackgroundWorker();
public MyForm()
{
InitializeComponents();
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.RunWorkerCompleted +=
backgroundWorker_RunWorkerCompleted;
backgroundWorker.RunWorkerAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
e.Result = LookForItWhichMightTakeALongTime();
}
private void backgroundWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
found = e.Result as MyClass;
}
}
And you can call RunWorkerAsync() from anywhere you want to, even from a Timer if you want. And just make sure to check if the BackgroundWorker is running already since calling RunWorkerAsync() when it's running will throw an exception.
private void timer_Tick(object sender, EventArgs e)
{
if (!backgroundWorker.IsBusy)
backgroundWorker.RunWorkerAsync();
}
timer.enabled = false
or
timer.stop();
and
timer.enabled = true
or
timer.start();
I use the System.Threading.Timer like so
class Class1
{
static Timer timer = new Timer(DoSomething,null,TimeSpan.FromMinutes(1),TimeSpan.FromMinutes(1));
private static void DoSomething(object state)
{
timer = null; // stop timer
// do some long stuff here
timer = new Timer(DoSomething, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
}
}