How to have a loop in a Windows service without using the Timer
There's another way to get timed execution, the WaitHandle.WaitOne() method provides a timeout argument. That works very nicely in a service as it lets you implement the need to stop the service and periodic execution in a single method call. The template looks like this:
Thread Worker;
AutoResetEvent StopRequest = new AutoResetEvent(false);
protected override void OnStart(string[] args) {
// Start the worker thread
Worker = new Thread(DoWork);
Worker.Start();
}
protected override void OnStop() {
// Signal worker to stop and wait until it does
StopRequest.Set();
Worker.Join();
}
private void DoWork(object arg) {
// Worker thread loop
for (;;) {
// Run this code once every 10 seconds or stop right away if the service
// is stopped
if (StopRequest.WaitOne(10000)) return;
// Do work...
//...
}
}
How will i achieve the endless loop without timer/thread in C# windows service?
You will have to do the work on another thread, or the windows service manager will assume your service hasn't started because the OnStart() never returns.
Your third-party library shouldn't work any differently, however the thread may require a different apartment model. Try creating an STA thread (see Starting an STAThread in C#) and seeing if that works, otherwise talk to the creator of the library.
Creating windows service without using timer control
A service does not repeat. It simply starts once, and then runs as long as it is not stopped. If it needs to do repeated tasks, you need to take care of the repeating yourself, in your code.
Of course, you could set up an ugly system with an endless for
-loop and a Thread.Sleep()
, but the issue there is, when starting a service, Windows expects the OnStart
to finish, so it can conclude that the service is started, rather than still starting up. The OnStart
function should prepare everything to make the service operations run, but it should not execute these operations itself.
So, the reason the timer is used for that is so the OnStart
function can finish correctly, and then after that, periodically, the service operations, in your case the GetFailedProductDetails()
function, can be started by the timer.
As for that piece of config, as I said in my comment, a bit of xml is not code. The guide you copied that from has explicitly written programming to read, interpret and apply these settings, to set up a Timer object to make it repeat in the configured intervals. Copying that xml without copying the accompanying code will do nothing to help you.
You can use the config file to set up the interval settings, of course, but then you'll also have to actually write the code to read them. The concept of a repeating service doesn't need such settings, though. You can perfectly program the service with a hardcoded half-hour interval and leave it at that.
Keep a Windows Service running without a timer
A windows service does not need to create a timer to keep running. It can either establish a file watcher Using FileSystemWatcher to monitor a directory or start an asynchronous socket listener.
Here is a simple TPL based listener/responder without needing to dedicate a thread to the process.
private TcpListener _listener;
public void OnStart(CommandLineParser commandLine)
{
_listener = new TcpListener(IPAddress.Any, commandLine.Port);
_listener.Start();
Task.Run((Func<Task>) Listen);
}
private async Task Listen()
{
IMessageHandler handler = MessageHandler.Instance;
while (true)
{
var client = await _listener.AcceptTcpClientAsync().ConfigureAwait(false);
// Without the await here, the thread will run free
var task = ProcessMessage(client);
}
}
public void OnStop()
{
_listener.Stop();
}
public async Task ProcessMessage(TcpClient client)
{
try
{
using (var stream = client.GetStream())
{
var message = await SimpleMessage.DecodeAsync(stream);
_handler.MessageReceived(message);
}
}
catch (Exception e)
{
_handler.MessageError(e);
}
finally
{
(client as IDisposable).Dispose();
}
}
Neither of these need a timer
Infinite while loop in Windows Service
To re-run the query every 40 seconds:
private const string Query = "SELECT * FROM 'reportsetting` order by SendingTime;"
protected override void OnStart(string[] args)
{
_timer = new Timer(40 * 1000); // every 40 seconds
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
_timer.Start(); // <- important
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
MySqlConnection con = new MySqlConnection(conn);
MySqlCommand comm = new MySqlCommand(Query, con);
con.Open();
MySqlDataReader dr = comm.ExecuteReader();
while (dr.Read())
{
time = dr["SendingTime"].ToString();
if ((str = DateTime.Now.ToString("HH:mm")).Equals(time))
{
//Execute Function and send reports based on the data from the database.
Thread thread = new Thread(sendReports);
thread.Start();
}
}
}
Something like that.
As Groo mentioned though, you might want to dispose of the connection every time so you don't have that hanging around in memory.
C# Windows Service While loop
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.
}
}
Best way to do a task looping in Windows Service
You should have an async method that accepts a CancellationToken
so it knows when to stop, calls ProccessSmsQueue
in a try-catch
block and uses Task.Delay
to asynchronously wait until the next time it needs to run:
public async Task DoWorkAsync(CancellationToken token)
{
while (true)
{
try
{
ProccessSmsQueue();
}
catch (Exception e)
{
// Handle exception
}
await Task.Delay(TimeSpan.FromMinutes(10), token);
}
}
You can call this method when your application starts and Task.Wait
the returned task before existing so you know it completes and has no exceptions:
private Task _proccessSmsQueueTask;
private CancellationTokenSource _cancellationTokenSource;
protected override void OnStart(string[] args)
{
_cancellationTokenSource = new CancellationTokenSource();
_proccessSmsQueueTask = Task.Run(() => DoWorkAsync(_cancellationTokenSource.Token));
}
protected override void OnStop()
{
_cancellationTokenSource.Cancel();
try
{
_proccessSmsQueueTask.Wait();
}
catch (Exception e)
{
// handle exeption
}
}
Related Topics
ASP.NET Button Onclick Event Not Firing
Programmatic Way to Get All the Available Languages (In Satellite Assemblies)
How Should You Diagnose the Error Sehexception - External Component Has Thrown an Exception
Add Timer to a Windows Forms Application
Getting the Index of a Particular Item in Array
How to Change Listbox Selection Background Color
Why Does Ienumerator<T> Inherit from Idisposable While the Non-Generic Ienumerator Does Not
JSON.Net Custom Serialization with JSONconverter - How to Get the "Default" Behavior
"The Linq Expression Node Type 'Invoke' Is Not Supported in Linq to Entities" - Stumped!
How to Add Option Groups in ASP.NET Drop Down List
Why Is Parallel.Foreach Much Faster Then Asparallel().Forall() Even Though Msdn Suggests Otherwise
Hide Form Instead of Closing When Close Button Clicked
How to Check for Nulls in a Deep Lambda Expression
Difference Between the Keydown Event, Keypress Event and Keyup Event in Visual Studio