My timer elapsed event does not fire in my windows service, why? I search in the forum but nothing of the solutions work for me.
In the main of program.cs:
static class program
{
static void Main()
{
#if DEBUG
servicioCR cr = new servicioCR();
cr.beginProcess();
#else
#endif
//ServiceBase[] ServicesToRun;
//ServicesToRun = new ServiceBase[]
//{
// new servicioCR()
//};
//ServiceBase.Run(ServicesToRun);
}
}
In my service class
public static System.Timers.Timer timer;
public servicioCR()
{
timer = new System.Timers.Timer(5000);
timer.AutoReset = false;
timer.Elapsed += timer_Elapsed;
InitializeComponent();
}
The elapsed event
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
timer.Stop();
//Do stuff
}
catch (System.Exception ex)
{
EventLog.WriteEntry(ex.Message);
}
finally
{
timer.Start();
}
}
And the beginProcess()
internal void beginProcess()
{
timer.Start();
}
I am using .NET Framework 4.5 and VS 2013... I don't understand why it doesn't work, I copied this from another solution that works fine.
If I put a breakpoint in one line of the Do stuff on the elapsed event, it never breaks.
Why? Thanks
Your timer is running, but the program closes itself before the timer ever fires. You need to put a pause of some kind in so your program does not close itself.
static void Main()
{
#if DEBUG
servicioCR cr = new servicioCR();
cr.beginProcess();
Console.WriteLine("Program Running");
Console.ReadLine();
#else
#endif
//ServiceBase[] ServicesToRun;
//ServicesToRun = new ServiceBase[]
//{
// new servicioCR()
//};
//ServiceBase.Run(ServicesToRun);
}
Here is a snippit of code from one of my older projects, this lets you run your program as both a service and a console app. In Visual studio just set the debugger to pass in the arguments --console in the setup project screen.
class Program
{
public static void Main(string[] args)
{
var example = new MyExampleApp();
if (args.Contains("--console"))
{
example.ConsoleRun(args);
}
else
{
ServiceBase.Run(example);
}
}
}
class MyExampleApp : ServiceBase
{
public void ConsoleRun(string[] args)
{
Console.WriteLine(string.Format("{0}::starting...", GetType().FullName));
OnStart(args);
Console.WriteLine(string.Format("{0}::ready (ENTER to exit)", GetType().FullName));
Console.ReadLine();
OnStop();
Console.WriteLine(string.Format("{0}::stopped", GetType().FullName));
}
//... the rest of the code from your service class.
}
Related
I am writing a C# Script control (WinForms). This is based on Dockpanelsuite, Scintilla, CSharpScriptingLibrary and a lot of code I wrote/collected in the last year. I want to include a prebuild "Logging" and a "ProgressBar" feature. So far I got everything to work as expected, except the fact it wont work correctly when using Timers.
The code written in the editor is compiled at runtime, the "Programm"-type is loaded and the "Main"-method is invoked. If the created assembly includes a "Log"-type the "LogMessage"-event will be connected to a method in the hosting script control, which forwards the messages to the Output-window.
As you can see the "Hello World" message is written to the Output-window, but each time the timer fires the LogMessage event in the static Log-Class is null.
Any idea what I have to change to share the LogMessage event from the UI thread with the Timer thread?
Programm.cs
using System;
using System.Timers;
namespace ScriptControl
{
public class Programm
{
Timer timer = null;
int step = 0, steps = 10;
public void Main()
{
Log.Write("Hello World");
try
{
timer = new Timer();
timer.Interval = 1000;
timer.Elapsed += TimerHandler;
timer.Enabled = true;
}
catch(Exception ex)
{
Log.Write(ex);
}
}
private void TimerHandler(object sender, object args)
{
if(this.step == 1) timer.Enabled = false;
Log.Write(step++.ToString());
Progress.Set(this.step, steps);
}
}
}
Log.cs
public delegate void LogHandler(object message);
public static class Log
{
public static event LogHandler LogMessage;
public static void Write(object message)
{
if(LogMessage != null)
LogMessage(message);
else
System.Windows.Forms.MessageBox.Show("LogMessage is null");
}
}
I created a windows service project with Visual Studio. This service should run in the background and poll data every X seconds. The polling is achieved with a timer and a tick event. So whenever the tick event is raised the service should do something.
Unfortunately the service closes itself because it does not wait for the timer to tick. The OnStart method gets executed and runs but after that the service closes itself.
I added a debug mode to my program file
private static void Main()
{
#if DEBUG
new RuntimeService().RunDebugMode();
#else
ServiceBase.Run(new RuntimeService());
#endif
}
and use this code for my service application
public partial class RuntimeService : ServiceBase
{
private const int BATCH_POLLING_INTERVAL = 3000;
private Timer batchPollingTimer;
public RuntimeService()
{
InitializeComponent();
}
public void RunDebugMode()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
try
{
// ...
batchPollingTimer = new Timer(BATCH_POLLING_INTERVAL);
batchPollingTimer.Elapsed += OnTimer;
batchPollingTimer.Enabled = true;
}
catch (Exception exception)
{
throw exception;
}
}
protected override void OnStop()
{
batchPollingTimer.Enabled = false;
try
{
// ...
}
catch (Exception exception)
{
throw exception;
}
}
private void OnTimer(object sender, ElapsedEventArgs e)
{
batchPollingTimer.Enabled = false;
// ...
batchPollingTimer.Enabled = true;
}
}
How can I run the service without closing it and waiting for the timer ticks? By "closing itself" I mean executing the Main method and ignoring the timer. Please let me know if you need more information.
It will only do this in debug mode, because there is nothing stopping it from ending. Ordinarily ServiceBase.Run will not return unless the service is shutting down. Add a sleep for a long time so that after your main thread has kicked off your timer, it will go to sleep rather than exiting the Main
Something like:
private static void Main()
{
#if DEBUG
new RuntimeService().RunDebugMode();
System.Threading.Thread.Sleep(TimeSpan.FromDays(1));
#else
ServiceBase.Run(new RuntimeService());
#endif
}
As an aside, consider putting your timer stop/start in a try/finally - at the moment if something happens in your OnTimer, your stopped timer will never restart and your service will cease doing anything (but may not crash entirely)
private void OnTimer(object sender, ElapsedEventArgs e)
{
try{
batchPollingTimer.Enabled = false;
// ...
} finally {
batchPollingTimer.Enabled = true;
}
}
}
I've code which starts depending whether the underlying application runs in console services instead of threads for the tasks. Here is a small cut of the main method:
//ANSAR BANK THREAD
Thread AnsarBankThread = new Thread(Ansar);
Console.WriteLine("Start The AnsarBankThread");
AnsarBankThread.Start();
//MELLAT BANK THREAD
Thread MellatBankThread = new Thread(Mellat);
Console.WriteLine("Start The MellatBankThread");
MellatBankThread.Start();
This is the code which will be executed:
static void Ansar()
{
var AnsarBank1 = new AnsarBank();
if (Environment.UserInteractive)
{
AnsarBank1.Start();
}
else
{
var servicesToRun = new ServiceBase[]{ AnsarBank1 };
ServiceBase.Run(servicesToRun);
}
}
static void Mellat()
{
var MellatBank1 = new MellatBank();
if (Environment.UserInteractive)
{
MellatBank1.Start();
}
else
{
var servicesToRun = new ServiceBase[]{ MellatBank1 };
ServiceBase.Run(servicesToRun);
}
}
and this is my AnsarBank service code:
protected override void OnStart(string[] args)
{
var timer = new System.Timers.Timer(5000); // fire every 30 second
timer.Elapsed += OnElapsedTime;
timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
File.WriteAllText(#"d:\Temp\Ansar.txt", "Ansar Bank Writer\n");
}
public void Start()
{
OnStart(new string[0]);
}
And this is my MellatBank Service:
protected override void OnStart(string[] args)
{
var timer = new System.Timers.Timer(5000); // fire every 30 second
timer.Elapsed += OnElapsedTime;
timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
File.WriteAllText(#"d:\Temp\MellatBank.txt", "Mellat Bank writer\n");
}
public void Start()
{
OnStart(new string[0]);
}
However, if I run the code there will be only the file Ansar.txt created and the file MellatBank.txt is missing!
Can someone encounter the problem in my code please? I would appreciate any help!
Chnage code to this:
System.Timers.Timer personalTimer = null;
public AnsarBank()
{
personalTimer = new System.Timers.Timer(5000);
InitializeComponent();
}
protected override void OnStart(string[] args)
{
//var timer = new System.Timers.Timer(5000); // fire every 30 second
personalTimer.Elapsed += OnElapsedTimeAnsar;
personalTimer.Enabled = true;
}
but so not work.
What's the problem?
1. Variable goes out of scope:
Thanks to #MatthewWatson: I also suggest moving the timer variable outside of the method right into the class. The timer object can be garbage collected directly because the garbage collector doesn't see that it's used any further.
Why thinks the gc that the variable isn't used anymore?
Simply because you created it in the method. It's local and because the class itself hasn't any reference to it there isn't any hint for the gc that it's needed further!
This should be true after I looked to this question.
Solution to this in sample code:
class SomeClass {
System.Timers.Timer personalTimer = null; //Timer is now garbage collected after the object of SomeClass goes out of scope!
SomeClass() {
personalTimer = new Syste.Timers.Timer(30000) // Now every 30 seconds!
}
protected override void OnStart(string[] args)
{
personalTimer.Elapsed += OnElapsedTime;
personalTimer.AutoReset = true; //Add this line to keep continuos activation
personalTimer.Enabled = true;
}
....
}
2.File access problems
After I tried your code I encountered exceptions because the path may not exist. So I changed the code to create a path before the creation of a file. Also I added checks whether file exists and if so that text will be applied to the file. The old solution replaced the file everytime. This works for me fine. I don't know what you've done with InitializeComponents(...) this seems to be gui stuff, so I don't know.
Change your code in the service classes to following please:
namespace WebService
{
partial class MellatBank : ServiceBase
{
System.Timers.Timer personalTimer = null;
public MellatBank()
{
personalTimer = new System.Timers.Timer(1000);
this.ServiceName = "MellatBankService";
}
protected override void OnStart(string[] args)
{
personalTimer.Elapsed += OnElapsedTimeMellat;
personalTimer.AutoReset = true; //Add this line to keep continuos activation
personalTimer.Enabled = true;
//var timer = new System.Timers.Timer(5000); // fire every 30 second
//personalTimer.Elapsed += OnElapsedTimeMellat;
//personalTimer.Enabled = true;
}
private void OnElapsedTimeMellat(object source, ElapsedEventArgs e)
{
try
{
if (!Directory.Exists(#"D:\Temp"))
Directory.CreateDirectory(#"D:\Temp\");
if (!File.Exists(#"D:\Temp\MellatBank.txt"))
{
var f = File.CreateText(#"D:\Temp\MellatBank.txt");
f.Write(#"D:\Temp\MellatBank.txt", "Mellat Bank writer\n");
f.Close();
}
else
{
var f = File.AppendText(#"D:\Temp\MellatBank.txt");
f.Write("Mellat Bank writer\n");
f.Close();
}
}
catch (System.Exception ex)
{
Console.Error.WriteLine("IO EXCEPTION: {0}", ex.ToString());
}
}
public void Start()
{
OnStart(new string[0]);
}
protected override void OnStop()
{
Console.Out.WriteLine("ended!");
// TODO: Add code here to perform any tear-down necessary to stop your service.
}
}
}
namespace WebService
{
partial class AnsarBank : ServiceBase
{
System.Timers.Timer personalTimer = null;
public AnsarBank()
{
personalTimer = new System.Timers.Timer(1000);
this.ServiceName = "AnsarBankService";
}
protected override void OnStart(string[] args)
{
personalTimer.Elapsed += OnElapsedTimeAnsar;
personalTimer.AutoReset = true; //Add this line to keep continuos activation
personalTimer.Enabled = true;
//var timer = new System.Timers.Timer(5000); // fire every 30 second
//personalTimer.Elapsed += OnElapsedTimeAnsar;
//personalTimer.Enabled = true;
}
private void OnElapsedTimeAnsar(object source, ElapsedEventArgs e)
{
try
{
if (!Directory.Exists(#"D:\Temp"))
Directory.CreateDirectory(#"D:\Temp\");
if (!File.Exists(#"D:\Temp\Ansar.txt"))
{
var f = File.CreateText(#"D:\Temp\Ansar.txt");
f.Write(#"D:\Temp\Ansar.txt", "Ansar Bank writer\n");
f.Close();
}
else
{
var f = File.AppendText(#"D:\Temp\Ansar.txt");
f.Write("Ansar Bank Writer\n");
f.Close();
}
}
catch (System.Exception ex)
{
Console.Error.WriteLine("IO EXCEPTION: {0}", ex.ToString());
}
}
public void Start()
{
OnStart(new string[0]);
}
protected override void OnStop()
{
Console.Out.WriteLine("ended!");
}
}
}
Edit:
After viewing your code I saw that your services only run as long as your application runs. So your services may have been stopped before they could write anything which would explain your problem too.
PS:
Asker please practice the basics of Object Oriented Programming (OOP) again if you don't know what class fields are.
Is it possible to optimise my console application? It uses up to 60% of CPU because of while(true) loop.
The idea is to kill Microsoft managment console (services) process every time it starts up. And to start/stop services - use pswrd and console.
public static void Main(string[] args)
{
Thread consoleInput = new Thread(_consoleInput);
consoleInput.Start();
killProcess();
}
static void _consoleInput(){
getPassword();
sendServiceCommands();
}
static void killProcess(){
while(true){
try{
System.Diagnostics.Process[] myProcs = System.Diagnostics.Process.GetProcessesByName("mmc");
myProcs[0].Kill();
}
catch(Exception e){}
}
}
You need System.Threading.Timer. Something like this:
public class Killer
{
protected const int timerInterval = 1000; // define here interval between ticks
protected Timer timer = new Timer(timerInterval); // creating timer
public Killer()
{
timer.Elapsed += Timer_Elapsed;
}
public void Start()
{
timer.Start();
}
public void Stop()
{
timer.Stop();
}
public void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
System.Diagnostics.Process[] myProcs = System.Diagnostics.Process.GetProcessesByName("mmc");
myProcs[0].Kill();
}
catch {}
}
}
...
public static void Main(string[] args)
{
Killer killer = new Killer();
Thread consoleInput = new Thread(_consoleInput);
_consoleInput.Start();
killer.Start();
...
// whenever you want you may stop your killer
killer.Stop();
}
This is my main:
static class Program
{
static void Main()
{
//Debugger.Launch();
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
And this is my Service1() code:
public partial class Service1 : ServiceBase
{
public Service1()
{
Thread messageThread = new Thread(new ThreadStart(Messaggi.Check));
messageThread.Start();
bool checkGruppoIndirizzi = true;
for (; ; )
{
SediOperative.Check();
Autisti.Check();
AutistiVeicoli.Check();
StatiVega.Check();
int res = Ordini.Check();
if (res == 0) AssegnazioniVega.Check();
Thread.Sleep(10000);
}
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
First thing is I don't know if launching two threads in that way is a good thing to do, but the real problem is the program run fine inside Visual Studio but after installation (I've created a setup project using InstallShield) I try to start my service from the windows service panel and I get:
Error 1053: The service did not respond to the start or control request in a timely fashion
The problem you have is that your service will be started sucessfully after the susyem has called the Start method and it has sucessfully returned. Given that you have an infinite loop in the constructor, the system is saying to itself something like "Can't even create the this let alone call start. I'm giving up.'
Your code should be refactored along these lines:
public partial class Service1 : ServiceBase
{
public Service1()
{
}
private Thread messageThread;
private Thread otherThread;
private bool stopNow;
protected override void OnStart(string[] args)
{
this.stopNow = false;
this.messageThread = new Thread(new ThreadStart(Messaggi.Check));
this.messageThread.Start();
this.otherThread = new Thread(new ThreadStart(this.StartOtherThread));
this.otherThread.Start();
}
private void StartOtherThread()
{
bool checkGruppoIndirizzi = true;
while (this.stopNow == false)
{
SediOperative.Check();
Autisti.Check();
AutistiVeicoli.Check();
StatiVega.Check();
int res = Ordini.Check();
if (res == 0) AssegnazioniVega.Check();
for (int 1 = 0; i < 10; i++)
{
if (this.stopNow)
{
break;
}
Thread.Sleep(1000);
}
}
}
}
protected override void OnStop()
{
this.stopNow = true;
this.messageThread.Join(1000);
this.otherThread.Join(1000);
}
}
And yes, starting stuff on Threads is exactly the way to do it! You'll have to have some way of stopping them in the Stop() method. (The code above is air code so don't trust it.) for the 'otherThread' I've got it checking a bool and exiting when the bool is set. the thread.Join is just a tidy-up which isn't strictly necessary, but is good housekeeping I think.
Cheers -