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)
I have created a simple Windows Service project to capture real time event from a fingerprint device using ZKemKeeper library. The service seems to work normally at the first time, and it responds well to the events in the device. But I found that, the service stop responding to the event after couple minutes of inactivity. I thought it was the service that caused the problem, but then the problem still there in WinForm application and even the samples included within the SDK showing the exact problem.
Here's the code for Windows Service:
public partial class Service1 : ServiceBase
{
private System.Diagnostics.EventLog eventLog1;
CZKEMClass myCZKEMClass;
public Service1()
{
InitializeComponent();
this.eventLog1 = new System.Diagnostics.EventLog();
((System.ComponentModel.ISupportInitialize)(this.eventLog1)).BeginInit();
this.eventLog1.Log = "MyLog";
this.eventLog1.Source = "MyLogSource";
((System.ComponentModel.ISupportInitialize)(this.eventLog1)).EndInit();
this.ServiceName = "ZKemKeeperTestService";
}
protected override void OnStart(string[] args)
{
myCZKEMClass = new CZKEMClass();
Thread createComAndMessagePumpThread = new Thread(() =>
{
myCZKEMClass.Connect_Net("192.168.1.20", 4370);
if (myCZKEMClass.RegEvent(1, 65535))
{
myCZKEMClass.OnAttTransactionEx += new _IZKEMEvents_OnAttTransactionExEventHandler(myCZKEMClass_OnAttTransactionEx);
}
Application.Run();
});
createComAndMessagePumpThread.SetApartmentState(ApartmentState.STA);
createComAndMessagePumpThread.Start();
eventLog1.WriteEntry("Service Started");
}
protected override void OnStop()
{
eventLog1.WriteEntry("Service Stopped");
myCZKEMClass.OnAttTransactionEx -= new _IZKEMEvents_OnAttTransactionExEventHandler(myCZKEMClass_OnAttTransactionEx);
}
private void myCZKEMClass_OnAttTransactionEx(string EnrollNumber, int IsInValid, int AttState, int VerificationMethod, int Year, int Month, int Day, int Hour, int Minute, int Second, int WorkCode)
{
eventLog1.WriteEntry(EnrollNumber.ToString());
}
}
I have no idea what's the cause of the problem and I'm stuck in there. FYI, I'm using the 64bit version of the library running in Windows 10. I'm using .NET Framework 4.0 as a target framework.
Achmad Mulyadi
I have same problem with you, please try to unregister the event than register again every 60 seconds, this work for me. I'm using 64bit version og the library running in windows 8.1
if (bIsConnected == true)
{
this.axCZKEM1.OnFinger -= new zkemkeeper._IZKEMEvents_OnFingerEventHandler(axCZKEM1_OnFinger);
this.axCZKEM1.OnVerify -= new zkemkeeper._IZKEMEvents_OnVerifyEventHandler(axCZKEM1_OnVerify);
this.axCZKEM1.OnAttTransactionEx -= new zkemkeeper._IZKEMEvents_OnAttTransactionExEventHandler(axCZKEM1_OnAttTransactionEx);
this.axCZKEM1.OnFingerFeature -= new zkemkeeper._IZKEMEvents_OnFingerFeatureEventHandler(axCZKEM1_OnFingerFeature);
this.axCZKEM1.OnEnrollFingerEx -= new zkemkeeper._IZKEMEvents_OnEnrollFingerExEventHandler(axCZKEM1_OnEnrollFingerEx);
iMachineNumber = 1;//In fact,when you are using the tcp/ip communication,this parameter will be ignored,that is any integer will all right.Here we use 1.
if (axCZKEM1.RegEvent(iMachineNumber, 65535))//Here you can register the realtime events that you want to be triggered(the parameters 65535 means registering all)
{
this.axCZKEM1.OnFinger += new zkemkeeper._IZKEMEvents_OnFingerEventHandler(axCZKEM1_OnFinger);
this.axCZKEM1.OnVerify += new zkemkeeper._IZKEMEvents_OnVerifyEventHandler(axCZKEM1_OnVerify);
this.axCZKEM1.OnAttTransactionEx += new zkemkeeper._IZKEMEvents_OnAttTransactionExEventHandler(axCZKEM1_OnAttTransactionEx);
this.axCZKEM1.OnFingerFeature += new zkemkeeper._IZKEMEvents_OnFingerFeatureEventHandler(axCZKEM1_OnFingerFeature);
this.axCZKEM1.OnEnrollFingerEx += new zkemkeeper._IZKEMEvents_OnEnrollFingerExEventHandler(axCZKEM1_OnEnrollFingerEx);
}
}
if you still not find the answer make Timer and put this code inside it
System.Windows.Forms.Application.DoEvents();
This will make the ActiveX to work
you can try to add this code in the thread.
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed += new System.Timers.ElapsedEventHandler((object sender, System.Timers.ElapsedEventArgs e) =>
{
string IPAddr = null;
if (axCZKEM1.GetDeviceIP(iMachineNumber, IPAddr))
{
LogHelper.Log(LogLevel.Debug, "device " + IPAddr + ":" + port + " connect status is ok.");
}
});
timer.Interval = 600000;// 10 minutes
timer.Enabled = true;
After looking every where for solution reading the manual multiple times I found that my issue was the firewall so try disabling firewall or add exception to your software
This is my first window service that I am writing, I need some help in writing it, I am trying to use single thread so that one thread can start the service
and the other thread can take care of calling the functions that does the database work. I am also using a timer so that this service only runs once a day below is my code
The reason i am posting this question is whenever I tried to install this service, it is throwing an error saying "fatal error occure", it doen't give me any details.
public partial class Service1 : ServiceBase
{
private DateTime _lastRun = DateTime.Now;
Thread workerThread;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
ThreadStart st = new ThreadStart(WorkerFunction);
workerThread = new Thread(st);
serviceStarted = true;
workerThread.Start();
}
protected override void OnStop()
{
// flag to tell the worker process to stop
serviceStarted = false;
// give it a little time to finish any pending work
workerThread.Join(new TimeSpan(0, 2, 0));
timer1.Enabled = false;
}
private void WorkerFunction()
{
while (serviceStarted)
{
EventLog.WriteEntry("Service working",
System.Diagnostics.EventLogEntryType.Information);
// yield
if (serviceStarted)
{
Thread.Sleep(new TimeSpan(0, 20000, 0));
}
timer1.Enabled = true;
timer1.Start();
}
// time to end the thread
Thread.CurrentThread.Abort();
}
private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (_lastRun.Date < DateTime.Now.Date)
{
timer1.Stop();
// does the actual work that deals with the database
}
timer1.Start();
}
There's a few things to check:
Be sure that you have configured the EventLog source correctly (MSDN). My answer to Windows service Started and stopped automatically, exception handling issue could be useful here also.
It looks like you are using a Windows Forms Timer - these require a UI message pump, which you won't have in a service (MSDN). You should instead investigate using the Timer class in the System.Threading namespace (MSDN).
In particular, you may find the using a System.Threading.Timer will simplify your code a great deal as this object will manage a bit more of the plumbing for you.
I would also advise against calling Thread.Abort(): it can be harmful and unpredictable, and in your case it doesn't appear that you need to use it at all. See To CurrentThread.Abort or not to CurrentThread.Abort and
http://msdn.microsoft.com/en-us/library/5b50fdsz.aspx.
I would like to use a timer instead of sleep within a windows service that should perform an action at a constant interval.
Lets say that I have the following class.
class MailManagerClient
{
//fields
string someString
//Constructor
public MailManagerClient()
{
aTimer = new System.Timers.Timer(30000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Enabled = true
}
//methode
public bool DoSomthingIncConstantInterval()
{
//Do Somthing
return true;
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
DoSomthingIncConstantInterval()
}
}
And I also have a windows service with the OnStart method.
I understand that in the OnStart method I will need to start a new thread for the type MailManagerClient.
But how do I start the thread? Which method should be the entry point for the new thread?
How should the thread stay alive?
Because you are starting the timer in the constructor than all you really need to do is instantiate a MailManagerClient in OnStart. You do not need to manually create a thread because System.Timers.Timer executes the Elapsed event handler on a thread from the ThreadPool.
public class MyService : ServiceBase
{
private MailManagerClient mmc = null;
protected void OnStart(string[] args)
{
mmc = new MailManagerClient();
}
}
I should point out that it would not be obvious to the next programmer looking at your code that MailManagerClient.ctor is actually doing anything. It would be better to define a Start method or something similar that enables the internal timer.
In the OnStart method you could have -
MailManagerClient m;
var th = new Thread(()=>m=new MailManagerClient());
th.Start();
You might also consider defining a Windows Task, as explained in this SO answer: What is the Windows version of cron?. The Windows OS will take care of scheduling and threading.
Just this - How do you add a timer to a C# console application? It would be great if you could supply some example coding.
That's very nice, however in order to simulate some time passing we need to run a command that takes some time and that's very clear in second example.
However, the style of using a for loop to do some functionality forever takes a lot of device resources and instead we can use the Garbage Collector to do some thing like that.
We can see this modification in the code from the same book CLR Via C# Third Ed.
using System;
using System.Threading;
public static class Program
{
private Timer _timer = null;
public static void Main()
{
// Create a Timer object that knows to call our TimerCallback
// method once every 2000 milliseconds.
_timer = new Timer(TimerCallback, null, 0, 2000);
// Wait for the user to hit <Enter>
Console.ReadLine();
}
private static void TimerCallback(Object o)
{
// Display the date/time when this method got called.
Console.WriteLine("In TimerCallback: " + DateTime.Now);
}
}
Use the System.Threading.Timer class.
System.Windows.Forms.Timer is designed primarily for use in a single thread usually the Windows Forms UI thread.
There is also a System.Timers class added early on in the development of the .NET framework. However it is generally recommended to use the System.Threading.Timer class instead as this is just a wrapper around System.Threading.Timer anyway.
It is also recommended to always use a static (shared in VB.NET) System.Threading.Timer if you are developing a Windows Service and require a timer to run periodically. This will avoid possibly premature garbage collection of your timer object.
Here's an example of a timer in a console application:
using System;
using System.Threading;
public static class Program
{
public static void Main()
{
Console.WriteLine("Main thread: starting a timer");
Timer t = new Timer(ComputeBoundOp, 5, 0, 2000);
Console.WriteLine("Main thread: Doing other work here...");
Thread.Sleep(10000); // Simulating other work (10 seconds)
t.Dispose(); // Cancel the timer now
}
// This method's signature must match the TimerCallback delegate
private static void ComputeBoundOp(Object state)
{
// This method is executed by a thread pool thread
Console.WriteLine("In ComputeBoundOp: state={0}", state);
Thread.Sleep(1000); // Simulates other work (1 second)
// When this method returns, the thread goes back
// to the pool and waits for another task
}
}
From the book CLR Via C# by Jeff Richter. By the way this book describes the rationale behind the 3 types of timers in Chapter 23, highly recommended.
Here is the code to create a simple one second timer tick:
using System;
using System.Threading;
class TimerExample
{
static public void Tick(Object stateInfo)
{
Console.WriteLine("Tick: {0}", DateTime.Now.ToString("h:mm:ss"));
}
static void Main()
{
TimerCallback callback = new TimerCallback(Tick);
Console.WriteLine("Creating timer: {0}\n",
DateTime.Now.ToString("h:mm:ss"));
// create a one second timer tick
Timer stateTimer = new Timer(callback, null, 0, 1000);
// loop here forever
for (; ; )
{
// add a sleep for 100 mSec to reduce CPU usage
Thread.Sleep(100);
}
}
}
And here is the resulting output:
c:\temp>timer.exe
Creating timer: 5:22:40
Tick: 5:22:40
Tick: 5:22:41
Tick: 5:22:42
Tick: 5:22:43
Tick: 5:22:44
Tick: 5:22:45
Tick: 5:22:46
Tick: 5:22:47
EDIT: It is never a good idea to add hard spin loops into code as they consume CPU cycles for no gain. In this case that loop was added just to stop the application from closing, allowing the actions of the thread to be observed. But for the sake of correctness and to reduce the CPU usage a simple Sleep call was added to that loop.
Lets Have A little Fun
using System;
using System.Timers;
namespace TimerExample
{
class Program
{
static Timer timer = new Timer(1000);
static int i = 10;
static void Main(string[] args)
{
timer.Elapsed+=timer_Elapsed;
timer.Start(); Console.Read();
}
private static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
i--;
Console.Clear();
Console.WriteLine("=================================================");
Console.WriteLine(" DEFUSE THE BOMB");
Console.WriteLine("");
Console.WriteLine(" Time Remaining: " + i.ToString());
Console.WriteLine("");
Console.WriteLine("=================================================");
if (i == 0)
{
Console.Clear();
Console.WriteLine("");
Console.WriteLine("==============================================");
Console.WriteLine(" B O O O O O M M M M M ! ! ! !");
Console.WriteLine("");
Console.WriteLine(" G A M E O V E R");
Console.WriteLine("==============================================");
timer.Close();
timer.Dispose();
}
GC.Collect();
}
}
}
Or using Rx, short and sweet:
static void Main()
{
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(t => Console.WriteLine("I am called... {0}", t));
for (; ; ) { }
}
You can also use your own timing mechanisms if you want a little more control, but possibly less accuracy and more code/complexity, but I would still recommend a timer. Use this though if you need to have control over the actual timing thread:
private void ThreadLoop(object callback)
{
while(true)
{
((Delegate) callback).DynamicInvoke(null);
Thread.Sleep(5000);
}
}
would be your timing thread(modify this to stop when reqiuired, and at whatever time interval you want).
and to use/start you can do:
Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop));
t.Start((Action)CallBack);
Callback is your void parameterless method that you want called at each interval. For example:
private void CallBack()
{
//Do Something.
}
You can also create your own (if unhappy with the options available).
Creating your own Timer implementation is pretty basic stuff.
This is an example for an application that needed COM object access on the same thread as the rest of my codebase.
/// <summary>
/// Internal timer for window.setTimeout() and window.setInterval().
/// This is to ensure that async calls always run on the same thread.
/// </summary>
public class Timer : IDisposable {
public void Tick()
{
if (Enabled && Environment.TickCount >= nextTick)
{
Callback.Invoke(this, null);
nextTick = Environment.TickCount + Interval;
}
}
private int nextTick = 0;
public void Start()
{
this.Enabled = true;
Interval = interval;
}
public void Stop()
{
this.Enabled = false;
}
public event EventHandler Callback;
public bool Enabled = false;
private int interval = 1000;
public int Interval
{
get { return interval; }
set { interval = value; nextTick = Environment.TickCount + interval; }
}
public void Dispose()
{
this.Callback = null;
this.Stop();
}
}
You can add events as follows:
Timer timer = new Timer();
timer.Callback += delegate
{
if (once) { timer.Enabled = false; }
Callback.execute(callbackId, args);
};
timer.Enabled = true;
timer.Interval = ms;
timer.Start();
Window.timers.Add(Environment.TickCount, timer);
To make sure the timer works you need to create an endless loop as follows:
while (true) {
// Create a new list in case a new timer
// is added/removed during a callback.
foreach (Timer timer in new List<Timer>(timers.Values))
{
timer.Tick();
}
}
In C# 5.0+ and .NET Framework 4.5+ you can use async/await:
async void RunMethodEvery(Action method, double seconds)
{
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(seconds));
method();
}
}
Use the PowerConsole project on Github at https://github.com/bigabdoul/PowerConsole or the equivalent NuGet package at https://www.nuget.org/packages/PowerConsole. It elegantly handles timers in a reusable fashion. Take a look at this sample code:
using PowerConsole;
namespace PowerConsoleTest
{
class Program
{
static readonly SmartConsole MyConsole = SmartConsole.Default;
static void Main()
{
RunTimers();
}
public static void RunTimers()
{
// CAUTION: SmartConsole is not thread safe!
// Spawn multiple timers carefully when accessing
// simultaneously members of the SmartConsole class.
MyConsole.WriteInfo("\nWelcome to the Timers demo!\n")
// SetTimeout is called only once after the provided delay and
// is automatically removed by the TimerManager class
.SetTimeout(e =>
{
// this action is called back after 5.5 seconds; the name
// of the timer is useful should we want to clear it
// before this action gets executed
e.Console.Write("\n").WriteError("Time out occured after 5.5 seconds! " +
"Timer has been automatically disposed.\n");
// the next statement will make the current instance of
// SmartConsole throw an exception on the next prompt attempt
// e.Console.CancelRequested = true;
// use 5500 or any other value not multiple of 1000 to
// reduce write collision risk with the next timer
}, millisecondsDelay: 5500, name: "SampleTimeout")
.SetInterval(e =>
{
if (e.Ticks == 1)
{
e.Console.WriteLine();
}
e.Console.Write($"\rFirst timer tick: ", System.ConsoleColor.White)
.WriteInfo(e.TicksToSecondsElapsed());
if (e.Ticks > 4)
{
// we could remove the previous timeout:
// e.Console.ClearTimeout("SampleTimeout");
}
}, millisecondsInterval: 1000, "EverySecond")
// we can add as many timers as we want (or the computer's resources permit)
.SetInterval(e =>
{
if (e.Ticks == 1 || e.Ticks == 3) // 1.5 or 4.5 seconds to avoid write collision
{
e.Console.WriteSuccess("\nSecond timer is active...\n");
}
else if (e.Ticks == 5)
{
e.Console.WriteWarning("\nSecond timer is disposing...\n");
// doesn't dispose the timer
// e.Timer.Stop();
// clean up if we no longer need it
e.DisposeTimer();
}
else
{
System.Diagnostics.Trace.WriteLine($"Second timer tick: {e.Ticks}");
}
}, 1500)
.Prompt("\nPress Enter to stop the timers: ")
// makes sure that any remaining timer is disposed off
.ClearTimers()
.WriteSuccess("Timers cleared!\n");
}
}
}
doc
There you have it :)
public static void Main()
{
SetTimer();
Console.WriteLine("\nPress the Enter key to exit the application...\n");
Console.WriteLine("The application started at {0:HH:mm:ss.fff}", DateTime.Now);
Console.ReadLine();
aTimer.Stop();
aTimer.Dispose();
Console.WriteLine("Terminating the application...");
}
private static void SetTimer()
{
// Create a timer with a two second interval.
aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0:HH:mm:ss.fff}",
e.SignalTime);
}
I suggest you following Microsoft guidelines (
https://learn.microsoft.com/en-us/dotnet/api/system.timers.timer.interval?view=netcore-3.1).
I first tried using System.Threading; with
var myTimer = new Timer((e) =>
{
// Code
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
but it continuously stopped after ~20 minutes.
With that, I tried the solutions setting
GC.KeepAlive(myTimer)
or
for (; ; ) { }
}
but they didn't work in my case.
Following Microsoft documentation, it worked perfectly:
using System;
using System.Timers;
public class Example
{
private static Timer aTimer;
public static void Main()
{
// Create a timer and set a two second interval.
aTimer = new System.Timers.Timer();
aTimer.Interval = 2000;
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
// Have the timer fire repeated events (true is the default)
aTimer.AutoReset = true;
// Start the timer
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program at any time... ");
Console.ReadLine();
}
private static void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
}
}
// The example displays output like the following:
// Press the Enter key to exit the program at any time...
// The Elapsed event was raised at 5/20/2015 8:48:58 PM
// The Elapsed event was raised at 5/20/2015 8:49:00 PM
// The Elapsed event was raised at 5/20/2015 8:49:02 PM
// The Elapsed event was raised at 5/20/2015 8:49:04 PM
// The Elapsed event was raised at 5/20/2015 8:49:06 PM
you can use StopWatch class, here's an example
StopWatch stopwatch = new Stopwatch();
// creating a new stopwatch class
stopwatch.Start();
// starting the stopwatch
Thread.Sleep(10000);
// waiting for 10 seconds
TimeSpan timespan = stopwatch.Elapsed;
/* creating a new timespan class and concacting it with the elapsed of the
stopwatch class */
string time = String.Format("{0:00}:{1:00}:{2:00}",
timespan.Hours, timespan.Minutes, timespan.Seconds
);
Console.Write($"The time right now is {time}");
Console.ReadKey();