I'm creating a windows service and after installing the service, it stops and starts immediately, but it shouldn't be at all. Previously, I was getting errors that the service was not responding to the start command in a timely fashion, so I took the init code out and put it in a thread, and now I am here:
protected override void OnStart(string[] args)
{
this.EventLog.WriteEntry("ATNotifier Started");
ThreadPool.QueueUserWorkItem(WaitOnEmailsChanged);
ThreadPool.QueueUserWorkItem(Init, "IP");
}
The waitonemailschanged thread simply creates a filesystemwatcher to watch to see if the settings file (xml document) gets changed, and loads in the data from that file if that happens. For the time being, this just waits indefinitely (which is the general case, as that will only be changed a few times a year), as no changes are being made to the xml document.
The Init thread does all kinds of things, including creating and starting a System.Timers.Timer object whose Elapsed method is the meat of the service.
I can't understand why it would start and then immediately stop. I should also note that the eventviewer shows no logs from this app.
edit> I tried creating 'proper' threads, with the same results and I've removed everything except the creating and starting of the timer like so:
protected override void OnStart(string[] args)
{
this.EventLog.WriteEntry("ATNotifier Started");
m_Timer = new System.Timers.Timer(90000.0); // 1.5 mins
m_Timer.Elapsed += new ElapsedEventHandler(m_Timer_Elapsed);
m_Timer.Start();
}
and I'm still getting the same message. It's almost as if the OnStart is never being called.
It might be stopped unexpectedly if your main thread terminates on exception.
The code you posted doesn't make sense to me. Why set an event handler before creating your Timer?
m_Timer.Elapsed += new ElapsedEventHandler(m_Timer_Elapsed);
m_Timer = new System.Timers.Timer(90000.0); // 1.5 mins
Shouldn't these two lines be swapped?
The problem turned out top be that the EventLog.WriteEntry was throwing an error because there was no EventSource associated with it. see http://msdn.microsoft.com/en-us/library/xzwc042w.aspx
As far as I can recall, you must actively report to the service manager that the service has successfully started - otherwise, the OnStart method will return, and if the status change has not been reported, the service manager will assume that the service terminated without actually successfully loading itself.
Reporting your service as having started successfully is done IIRC by the Service base class, so add the following to the bottom of the OnStart method:
base.OnStart(args);
ThreadPool threads are background threads; they won't keep a process alive. I suspect you need a "proper" thread...
Try: new Thread(SomeCode).Start(); or similar.
Related
Actually, when I want to stop my worker on azure, this function is called.
public override void OnStop()
{
if (messageProvider != null)
{
messageProvider.StopListening();
}
base.OnStop();
}
When I upgrade the worker, If there is any message beeing processed, I lose that message. Do you know how can I safely stop my worker?
You have five minutes, from the time OnStop() is called, and before OnStop() exits, to finish your current processing (whatever that means). In your case, it looks like you have some type of message provider, and you're able to disengage from message-consumption via messageProvider.StopListening();. Since you're concerned with processing of current message, you'd likely need some type of signal to let you know that there are no messages being processed (including ones that may have been read, but not processed, by the time you called StopListening()), and that it's safe to exit from OnStop(). How you implement the signal is up to you, but you'd need to wait for the signal within Onstop().
FYI info about OnStop() and the five-minute window is here.
I have a project in Xamarin.IOS which interacts with a UI component via NSEvents. UI sends messages through events with a payload - google's protobuf encoded objects. UI is written in ObjC, the logic is written in C#.
Each NSEvent is caught in an observer that invokes internal logic which begins the processing of a message. These messages are put into a queue and eventually taken by threads from the queue.
When a message arrives, the program can create a thread for it, and that's the place where it fails. The code is legacy, so we are using Thread. I write
Thread t = new Thread(ThreadProc);
t.IsBackground = true;
t.Start();
The code used to work a short while ago, also it works sometimes. Sometimes the thread is simply not created. No error is reported.
If I create a thread not in a context of an observer, the thread is started.
I have no idea why it may happen. The problem arises in the very initialization of the application, when the first thread is about to be created. So I don't think there are too many threads.
I have tried to re-create it with Task interface. Tasks are created and started alright, but I can not migrate entire solution to Tasks, unfortunately.
I guess there is some configuration issue or like that since it used to work. I just don't get what it might be. What can affect Thread.Start()?
UPD: I've rolled back to a very old commit which used to work, now it fails too. So it seems not to be a configuration issue, but ios/xamarin issue.
I've never seen anything remotely similar (creating and starting a Thread not actually doing anything), so my first thought is to ensure that this code is actually executed in the first place.
Can you add a Console.WriteLine statements like this:
Console.WriteLine ("creating thread");
Thread t = new Thread(() =>
{
Console.WriteLine ("executing ThreadProc");
try {
ThreadProc ();
} finally {
Console.WriteLine ("finished executing ThreadProc");
}
});
t.IsBackground = true;
t.Start();
Console.WriteLine ("started thread");
and then see what actually shows up in the application output?
Application logging is done using plain and boring log files via a custom rolling flat file logging library. To lower the amount of write accesses to the hard disk, logging events get queued for either when a) a maximum queue item limit is reached or b) a certain amount of time has passed. For the time interval aspect, the logging library runs a thread which flushes the queue periodically.
Now, the logging instance is statically accessible, singleton and application wide (used in many other libraries) and sometimes it happens (altough it shouldn't) that a developer forgets to dispose the flushing thread with the result that, even if the application is 'closed', the thread keeps running and the application has to be killed via a task-manager, which is far from ideal.
So I'm wondering: Is there a possibility to automatically close the thread on application exit? I know about BackgroundWorker, Timer and Threadpool, but are those good solutions for that certain task? Or better stick with the 'classic' Thread?
Detecting that an application is about to exit is very specific to what kind of application you're running.
I don't know much about Aspx, but in WPF you could use the following code to hook up the Exit event of the System.Windows.Application class and close your thread gracefully in the event handler.
Also, you should always avoid killing a thread instead of shutting down gracefully, when it's possible, it can lead to inconsistencies because you have no way of controlling when it will really exit. Instead, you should periodically check for an exit condition, like in the code below.
public static class MyLogger
{
public static void Initialize()
{
if(IsWPFApplication())
Application.Current.Exit += Application_Exit;
//start flush thread and other initializations...
}
private static bool IsWPFApplication()
{
Dispatcher dispatcher = Dispatcher.FromThread(Thread.CurrentThread);
return (dispatcher != null);
}
private static void Application_Exit(Object sender, EventArgs e)
{
Shutdown();
}
private static void Shutdown()
{
ExitRequested = true;
}
}
You can use System.Diagnostic.Process.GetCurrentProcess.Kill though if you are using dot net 4.0 I would recommend using tasks. Here is an excellent resource that I would recommend http://www.albahari.com/threading/.
I'm trying to write a Windows service that runs indefinitely. Windows forms and background programs for Linux don't seem too bad but maybe I'm just horribly inept at Windows Services. Unlike some other sleep or timer related questions I've dug through here, the time to wake up or sleep can be a regular interval, but isn't always such. The program reads from some data files that may instruct it to change its own schedule and this must take effect as of its next wake up time. It seemed quite easy as a console program and behaved perfectly there:
while (true)
{
// Calculate next time to run.
DateTime nextRun = NextWakeup();
TimeSpan nextTime = nextRun - DateTime.Now;
int sleepMs = (int)nextTime.TotalMilliseconds;
// Sleep until scheduled time
System.Threading.Thread.Sleep(sleepMs);
// Do a code cycle of more stuff here...
}
However, when I try to run it as part of a service so that it continues to be active while the user is logged out, the Service Manager stubbornly refuses to start it. I get the lovely 1053 error, "The service did not respond to the start or control request in a timely fashion."
A lot of answers to related questions here seem to suggest going with a timer at all costs over thread sleeping. If I did such a thing instead of the while/sleep combination, how would I go about changing the timer interval at each run? Or is this all perfectly fine and I'm going about setting up my service wrong?
Much thanks in advance!
Windows services must usually respond to a control request (ususally start/stop but also pause/resume) in 30seconds. This means that if you sleep the main thread in the OnStart your service will return the error you refer to.
The way to resolve your issue is to do your work on a separate thread, where you're free to sleep the thread in the way you describe. Just start this thread in the services' OnStart and you should be able to easily return within the 30 second limit.
As an aside, instead of while(true) you should consider the service being stopped must also return in that 30 second limit. If you have a thread sat sleeping the service will not shut down properly without either Aborting the thread (bad) or providing some mechanism for properly exiting the thread. This is exactly why most people go with the polling approach; the service can both determine whether its time to run, or determine whether a stop request has taken place. As long as this poll freqency is <30s the service will always shut down properly.
If you want to use timers its quite easy to do. I'd use System.Timers.Timer and changing its interval is as easy as mytimer.Inverval = nextTime.Seconds or similar.
I'd personally run the timer without AutoReset = false (so it doesn't restart the timer automatically) and then every time it wakes up it runs your "dowork" and then at the end of the dowork you work out when you want it to run next, set the interval as appropriate and then call Start on your timer again.
Of course in your service your start method just sets up the first timer run and then returns so that the startup is nice and quick. On shutdown you just clean up your timer (stop and dispose and such like) and then just return. Nice and clean.
I think you might be looking for something like this:
static class ConsoleProgram
{
static void Main()
{
ServiceBase[] servicesToRun = new ServiceBase[] { new MyService(config, Logger) };
ServiceBase.Run(servicesToRun);
}
}
public partial class MyService : ServiceBase
{
private bool _stopped = true;
protected override void OnStart(string[] args)
{
StartTimer();
}
protected override void OnStop()
{
StopTimer();
}
public void StartTimer()
{
_stopped = false;
Timer t = new Timer(TimerProc);
// Calculate your desired interval here.
t.Change(_config.Interval, new TimeSpan(0, 0, 0, 0, -1));
}
public void StopTimer()
{
_stopped = true;
}
private void TimerProc(object state)
{
// The state object is the Timer object.
Timer t = (Timer) state;
t.Dispose();
ThreadPool.QueueUserWorkItem(DoWork);
if (!_stopped) {
StartTimer();
}
}
}
Whilst debugging my program in VS 2008 I have come across the following error:
The CLR has been unable to transition from COM context 0x34fc1a0 to COM context 0x34fc258 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this
It appears to be deadlocking even though the code only contains a simple C# timer: See Snippet Below:
private void RequestWork()
{
// The timer will be re-intialised if there are still no wating jobs in the database
StopTimer();
// assign all the threads some work
InitialiseTimer();
}
/// <summary>
/// Initialise a timer with a timer interval configured from app.config. Enable the timer and
/// register an appropriate event handler
/// </summary>
private void InitialiseTimer()
{
if (m_Timer == null)
{
// look up the default backoff time from the config
string backOffInt = ConfigurationSettings.AppSettings["BackOffInterval"];
int backoffInterval = 1000;
m_Timer = new System.Timers.Timer();
// set the timer interval to 5 seconds
m_Timer.Interval = backoffInterval;
m_Timer.Elapsed += new ElapsedEventHandler(m_Timer_Elapsed);
}
m_Timer.Enabled = true;
}
private void StopTimer()
{
if (m_Timer != null)
{
m_Timer.Enabled = false;
}
}
void m_Timer_Elapsed(object p_Sender, ElapsedEventArgs p_E)
{
RequestWork();
}
As far as I know the timer should run, elapse and then initialise again, I can see no local reason for a deadlock.
I am aware of how to turn this error msg off but feel that this is not a solution, instead it is masking the problem.
You can turn this off if you think you've definitely not got a deadlock situation:
Debug->Exceptions->Managed Debug Assistants menu in Visual Studio and uncheck the ContextSwitchDeadlock
This is an infinite loop. You need to let your application pump some messages at least once every 60 seconds to prevent this exception to happen.
Try calling System.Threading.Thread.CurrentThread.Join(10) once in a while. There are other calls you can do that let the messages pump.
It seems that you are adding a new event handler each time you call InitialiseTimer. That way m_Timer_Elapsed will be called as many times as it has been added.
You should add the event handler just one time.
If your application hangs or not reponse even after you uncheck the box against contextswitchdeadlock. Put the following line before call of method or for loop.
In C#
System.Windows.Forms.Application.DoEvents();
and VB.NET / VB / ASP.NET
DoEvents()
Couple thoughts/questions:
1) The code snippet looks like your interval is every 1 second (not 5 as mentioned in the comments).
2) The big question is what is RequestWork() doing?
Without knowing what RequestWork() is doing, we can't really comment on why you are seeing a ContextSwitchDeadlock.
Somethings to think about with respect to this method
a) how long does it take?
b) is it accessing GUI elements?
Some MSDN comments on Elapsed:
If you use the Timer with a user
interface element, such as a form or
control, assign the form or control
that contains the Timer to the
SynchronizingObject property, so that
the event is marshaled to the user
interface thread.
-and-
The Elapsed event is raised on a
ThreadPool thread. If processing of
the Elapsed event lasts longer than
Interval, the event might be raised
again on another ThreadPool thread.
Thus, the event handler should be
reentrant.
I'm thinking since you have a 1 second timer, you might want to look into what happens in RequestWork and see how long its taking.