after reading this stack overflow page and this other one.
I didn't really found an answer to my question, I was asking myself why is my service stopping after one loop althought is works fine in debug mode (visual studio).
Here is the code I have
public partial class Service1 : ServiceBase
{
Timer t;
// some more stuff
public Service1()
{
InitializeComponent();
// some more stuff
t = new Timer();
t.Interval = 1000 * 5; // timer of 5 secs.
t.Elapsed += new ElapsedEventHandler(this.onTimer);
t.Start();
}
protected void onTimer(object sender, ElapsedEventArgs args)
{
t.Stop(); // stop the timer to prevent callung the function 2 times in parallel
int tag = 1;
while (tag == 1)
{
tag = doStuff(); // return 1 if it needs to continu looping, return 0 when done
}
t.Start();
}
}
My problem is that doStuff() gets called one time, loop only once, and never get called again (I know this thanks to a log.txt file that I din't show up in the exemple)
Related
When my app goes in background, a timer starts ( in OnStop() override)
This time just perform a query every 10 seconds.
If the result "x", thanI create a notification, and dispose timer. Now I can either click the notification or resume the app.
But if i want to use the App resuming it, it get stuck in the "stopped" layout, and I see timer doesn't die (from console).
I tried to stop it in OnResume(), OnStart(), OnRestart()but none of these get called, timer still goes and app crashes.
I'm pretty sure my way to check database update in background is very bad, but I would like to use this way.
The times is made like this:
public class TimerExampleState
{
public int counter = 0;
public Timer tmr;
}
protected override void OnStop()
{
base.OnStop();
GlobalVar.KillTimer = 0;
StuffInStop();
}
public void StuffInStop()
{
TimerExampleState s = new TimerExampleState();
TimerCallback timerDelegate = new TimerCallback(CheckStatus);
Timer timer = new Timer(timerDelegate, s, 1000, 10000);
s.tmr = timer;
while (s.tmr != null)
Thread.Sleep(0);
}
public async void CheckStatus(Object state)
{
TimerExampleState s = (TimerExampleState)state;
s.counter++;
if (s.counter == 2)
{
int x = await AsyncIntCheck();
if (GlobalVar.KillTimer == 1)
{
Console.WriteLine("disposing of timer...");
s.tmr.Dispose();
s.tmr = null;
}
s.counter = 1;
}
}
the AsyncIntCheck is the fucntion checking for updates (it is a int function because later it will return the number of updatet parts).
As you can imagine I've a global int, when I create notification, i set GlobalVar.KillTimer to 1 and timer get killed.
I hope I wrote everything needed, just for redundancies, I want kill timer when user resume app.
Thanks.
My company has developed a Windows Service Application and it was installed in some customers.
They are complaining that the Service stops after continuously running for a few days.
I can't reproduce the error and I do not have any stack trace. All I have is a generic message in Event Viewer:
The 'myservicename' service terminated unexpectedly. It has done this 1 time(s).
My code:
private System.Timers.Timer myTimer;
private readonly Queue<FileInfo> MyQueue = new Queue<FileInfo>();
protected override void OnStart(string[] args)
{
myTimer = new System.Timers.Timer(1000 * 60 * 1); // 1 min
myTimer.Elapsed += new ElapsedEventHandler(MyMethod);
myTimer.Start();
SomeSafeTasks();
try
{
CreateSomeThreads();
}
catch(Exception)
{
//log
}
}
public void MyMethod()
{
lock (MyQueue) // there are other places with lock
{
if(MyQueue.Count == 0)
{
// code with try catch
}
}
}
I believe that the error is related with the Timer being GC'ed.
Does it make sense? The code above may break after running some days?
How do I estimate when it will break? It is strange for me that it runs for a week. I would expect that it would be GC'ed in 15 minutes or 1 hour.
Is it 100% safe to add GC.KeepAlive(myTimer) after myTimer.Start()?
Will it run forever or do I need to call GC.KeepAlive sometimes?
I have an application that uses a timer to 1 in 1 minute perform refresh data in a DataGridView. Depending on the information to return the screen, a different sound will play. Each sound has a playback time. I am using this command to have the effect of duration of my music.
Thread.sleep(GetMusicDuration[i] * 1000);
When I start my application the first time, everything goes well, but when the timer runs TICK event that carries the information in the DataGridView again and run PLAY to play the sounds my Thread.Sleep command does not work, it simply ignores not expect the time set for parameter.
public void PlaySound()
{
try
{
while (1 == 1)
{
List<string> distinctMusic = GetMusicFile.Distinct().ToList();
StopSound();
if (distinctMusic.Count > 0)
{
for (int i = 0; i < distinctMusic.Count; i++)
{
player.SoundLocation = distinctMusic[i];
player.Play();
Thread.Sleep(GetMusicDuration[i] * 1000);
StopSound();
}
}
DisposePlayer();
}
}
catch (Exception e)
{
if (generateLog)
log.LogTxt(e.ToString());
}
}
Until now I did not understand why the exucução wrong.
someone could help me?
thank you...!
Thread.Sleep blocks the UI thread. You should use a timer in stead:
//Create a new timer that ticks every xms
var t = new System.Timers.Timer (GetMusicDuration[i] * 1000);
//When a tick is elapsed
t.Elapsed+=(object sender, System.Timers.ElapsedEventArgs e) =>
{
//what ever you want to do
};
//Start the timer
t.Start();
I created windows service on C#.
For now I have methods for scanning DB.
I need call this method two times per minute. Actually I don't know method for waiting in windows service.
I tried Thread.Sleep... but nothing happened.
Please help me with this problem.
private int wait;
protected void Start()
{
wait = 1000;
while (true)
{
if (wait < 30000)
wait += wait;
//implement logic for waiting
Video video = new Video();
video.FindFileForConvert();
if (video.Path != null)
{
Console.WriteLine("video != null. video path = {0}", video.Path);
video.BeginConvertation();
video.DeleteOriginFile();
wait = 1000;
}
}
}
You should use System.Threading.Timer for the same. Since Thread.sleep is not a good practice atleast in some cases.
You may use Timer
public static int Main() {
/* Adds the event and the event handler for the method that will
process the timer event to the timer. */
myTimer.Tick += new EventHandler(TimerEventProcessor);
// Sets the timer interval to 5 seconds.
myTimer.Interval = 5000;
myTimer.Start();
// Runs the timer, and raises the event.
while(exitFlag == false) {
// Processes all the events in the queue.
Application.DoEvents();
}
return 0;
}
I may be mistaken, but I think that this code will help you resolve your problem. DispatcherTimer
DispatcherTimer dispathcerTimer = new DispatcherTimer();
dispathcerTimer.Interval = TimeSpan.FromMinutes(2);
dispathcerTimer.Tick += dispathcerTimer_Tick;
dispathcerTimer.Start();
void dispatcherTime_Tick(object sender, object e)
{
//function, which needs to be invoked every two minutes.
}
I have a created a windows service and created installer for it. It is installed and started but the code i have written inside it is not executing. actually when i start the service from the service window the OnStart() function is not fired. nor the initializecomponent() nor the static void main function.. can any one help me with it
please guide me where i have done wrong.
here are some code lines. let me know if u want more of what i have written
public partial class iMArchiveService : ServiceBase
{
Boolean isArchiving = false;
public iMArchiveService()
{
MyException.CreateLog("iMArchiveService: Inside Constructor. Initializing Component");
InitializeComponent();
MyException.CreateLog("iMArchiveService: Component Initialized. Timer is set as: " + TimeMachine.Interval.ToString() + " milliseconds");
}
protected void TimeMachine_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
MyException.CreateLog("iMArchiveService: Inside Tick Try. Value of isArchiving variable before condition is: " + isArchiving.ToString());
if (!isArchiving)
isArchiving = new iM.OrderArchiving.ArchiveOrderXML().ArchiveOrderService();
MyException.CreateLog("iMArchiveService: Inside Tick Try. Value of isArchiving variable after condition is: " + isArchiving.ToString());
}
catch (Exception ex)
{
MyException.CreateLog("iMArchiveService: Inside Tick Catch :(");
}
}
protected override void OnStart(string[] args)
{
TimeMachine.Enabled = true;
MyException.CreateLog("iMArchiveService Started: " + DateTime.Now.ToString());
}
protected override void OnStop()
{
TimeMachine.Enabled = false;
MyException.CreateLog("iMArchiveService Stopped: " + DateTime.Now.ToString());
}
}
the code above is for service file.cs
here is my project installer file
namespace iM.OrderArchivingService
{
[RunInstaller(true)]
public partial class ProjectInstaller : Installer
{
public ProjectInstaller()
{
InitializeComponent();
}
}
}
here is the InitializeComponenet Function -
private void InitializeComponent()
{
this.myServiceProcessInstaller = new System.ServiceProcess.ServiceProcessInstaller();
this.myServiceInstaller = new System.ServiceProcess.ServiceInstaller();
//
// myServiceProcessInstaller
//
this.myServiceProcessInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
this.myServiceProcessInstaller.Installers.AddRange(new System.Configuration.Install.Installer[] {
this.myServiceInstaller});
this.myServiceProcessInstaller.Password = null;
this.myServiceProcessInstaller.Username = null;
//
// myServiceInstaller
//
this.myServiceInstaller.ServiceName = "iMArchiveService";
//
// ProjectInstaller
//
this.Installers.AddRange(new System.Configuration.Install.Installer[] {
this.myServiceProcessInstaller});
}
here is the program.cs file
namespace iM.OrderArchivingService
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new iMArchiveService() };
ServiceBase.Run(ServicesToRun);
}
}
}
as u see i have written the code to log when in initializes or starts.. but no log is being made.
edit:
Code for Timer(TimeMachine)
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.TimeMachine = new System.Timers.Timer(3600000);
//
// TimeMachine
//
this.TimeMachine.Interval = 3600000;
this.TimeMachine.Elapsed += new System.Timers.ElapsedEventHandler(TimeMachine_Elapsed);
//
// iMArchiveService
//
this.ServiceName = "iMArchiveService";
}
thnx
You're using the wrong Timer class - the clue is in its namespace: System.Windows.Forms.Timer. That timer only works in WinForms applications.
You should, instead, switch to using System.Timers.Timer
There is a general discussion of the timer classes in System.Threading.Timer:
System.Threading.Timer is a simple, lightweight timer that uses callback methods and is served by thread pool threads. It is not recommended for use with Windows Forms, because its callbacks do not occur on the user interface thread. System.Windows.Forms.Timer is a better choice for use with Windows Forms. For server-based timer functionality, you might consider using System.Timers.Timer, which raises events and has additional features.
(My emphasis replaces original)
Don't use System.Windows.Forms.Timer in windows service, it might not raise events in it. See The Windows Forms Timer event is not raised in a Windows service.
Use either System.Timers.Timer or System.Threading.Timer in windows service. See Windows service and timer.
Please check TimeMachine.Enable = True and have you set timing for timer or not.
refer this link
http://codesimplified.com/2010/12/31/creating-window-service-with-net-vs2008/
Maybe you should use the Timer.Start() and Timer.Stop() methods to start and stop the timer instead, just in case there is a problem using the Enabled property.
The interval period is 3,600,000 which is 3600 seconds or 60 minutes = 1 hour. Nothing will happen until an hour has passed by; this is what you intended?
BTW, setting the interval like the examples below will make your code a little easier to read:
this.TimeMachine.Interval = 1 * 1000; // 1 Second
this.TimeMachine.Interval = 60 * 1000; // 60 Seconds
this.TimeMachine.Interval = 60 * 60 * 1000; // 1 hour
Try using the Debug.Writeline() method in System.Diagnostics. By default that will post messages in the Output window in MSVS. You'll also see any exceptions there too.