Windows Service to Run Constantly

Windows Service to run constantly

The OnStart() callback needs to return in a timely fashion, so you'll want to kick off a thread where all your work will be performed. I would recommend adding the following fields to your class:

using System.Threading;
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private Thread _thread;

The _thread field will hold a reference to the System.Threading.Thread object you create in the OnStart() callback. The _shutdownEvent field holds a system-level event construct that will be used to signal the thread to stop running on service shutdown.

In the OnStart() callback, create and start your thread.

protected override void OnStart(string[] args)
{
_thread = new Thread(WorkerThreadFunc);
_thread.Name = "My Worker Thread";
_thread.IsBackground = true;
_thread.Start();
}

You need a function named WorkerThreadFunc in order for this to work. It has to match the System.Threading.ThreadStart delegate signature.

private void WorkerThreadFunc()
{
}

If you don't put anything in this function, the thread will start up and then immediately shutdown, so you have to put some logic in there that basically keeps the thread alive while you do your work. This is where the _shutdownEvent comes in handy.

private void WorkerThreadFunc()
{
while (!_shutdownEvent.WaitOne(0)) {
// Replace the Sleep() call with the work you need to do
Thread.Sleep(1000);
}
}

The while loop checks the ManualResetEvent to see if it is "set" or not. Since we initialized the object with false above, this check returns false. Inside the loop, we sleep for 1 second. You'll want to replace this with the work you need to do - monitor proxy settings, etc.

Finally, in the OnStop() callback of your Windows Service, you want to signal the thread to stop running. This is easy using the _shutdownEvent.

protected override void OnStop()
{
_shutdownEvent.Set();
if (!_thread.Join(3000)) { // give the thread 3 seconds to stop
_thread.Abort();
}
}

Hope this helps.

windows service is still running but the task is not executed continuously

The problem is, that your OnStart() method already does the concrete job and never returns. But the Service Manager is designed, that it waits max 60 secs till the OnStart() method returns, otherwise the process will be killed.

So, instead of directly calling within your OnStart() method your code, you should instantiate a new Task or Thread that will do the work and immediately exit the OnStart() method. Within the OnStop() method you have to inform your parallel running code to stop (e.g. by using a CancellationToken) and wait till it's done and then exit.

Example

public partial class ServiceExample : ServiceBase
{
public ServiceExample()
{
InitializeComponent();
}

private Task Runner;
private CancellationTokenSource Cts;

protected override void OnStart(string[] args)
{
if (Cts != null) // Could also simply return
throw new InvalidOperationException("Service is already running!");

Cts = new CancellationTokenSource();

Runner = DoSomething(Cts.Token);
}

private async Task DoSomething(CancellationToken cancellationToken)
{
// Immediately return to caller to avoid "hanging" OnStart()
await Task.Yield();

// Regulary check if OnStop() is waiting for us
while (!cancellationToken.IsCancellationRequested)
{
// Call your method that should do something.
// If it runs longer and can be intercepted,
// forward the CancellationToken to it.
await Worker(cancellationToken);
}
}

protected override void OnStop()
{
if (Cts == null) // Could also simply return
throw new InvalidOperationException("Service already being stopped!");

Cts.Cancel();
Runner.Wait();
}

private async Task Worker(CancellationToken cancellationToken)
{
Trace.WriteLine($"{DateTime.UtcNow}: Do some heavy work!");
await Task.Delay(TimeSpan.FromSeconds(1));

if (cancellationToken.IsCancellationRequested)
return;

await Task.Delay(TimeSpan.FromSeconds(1));
}
}

How do I get my Windows Service to keep running?

See that your class has no errors, an error there could throw you whole service out.
Also try putting your timer into a method and only call it, not have it in your service code.

A windows service should always be made as an empty shell that just call's methods.

How do I run a windows service in every one hour?

Windows services are supposed to run continuously - If you just need it to "wake up" once an hour why not to make it a Scheduled Task instead?


With Scheduled Tasks all you need is to compile your code and then you can "Create Task", direct it to your exe and set when to run.
Sample Image

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

C# Windows service re-run only after a method completes

Set the AutoReset property of the timer to false, this will make the timer only run once, then at the end of your tick function you restart the timer.

protected override void OnStart(string[] args)
{

timer1 = new Timer();
this.timer1.Interval = 2000; //every 2 seconds
this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Tick);
timer1.AutoReset = false;
timer1.Enabled = true;
Helper.ServiceStartLog("Test window service started");
}

private void timer1_Tick (object sender, ElapsedEventArgs e)
{
try
{
PDFHelper.WriteErrorLog("Timer ticker and Log Running Job is Running");
}
finally
{
//this gets run even if there was a exception.
timer1.Start();
}
}


Related Topics



Leave a reply



Submit