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.
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
How to Find All Possible Subsets of a Given Array
How to Clean HTML Tags Using C#
Stroke Width Transform (Swt) Implementation (Java, C#...)
Getting HTML Body Content in Winforms Webbrowser After Body Onload Event Executes
Return HTML from ASP.NET Web API
How to Verify Text Is Bold Using Selenium on an Angular Website with C#
How to Add CSS Class to HTML Generic Control Div
ASP.NET Core 2.0-2.2 Kestrel Not Serving Static Content
ASP.NET - Problems with Static Selected Style for a Selected Page on the Menu
ASP.NET Adding Class to Current Menuitem
Set Gridview Backcolor to Color from Datatable
Remove CSS Class in Code Behind
Publishing a Website Is Not Updating My CSS Bundles
How to Cast String to Int. Error Msg: Input String Was Not in a Correct Format
How to Convert JavaScript Datetime to C# Datetime
5.7.57 Smtp - Client Was Not Authenticated to Send Anonymous Mail During Mail from Error