C# Timers stopping intermittently - c#

Can anybody suggest any reasons why a C# timer (created in a code-behind class) would stop without being told to?
My timer starts on page load and then stops when I click a button. I don't need to click the button for it to sometimes stop. IIS is not being restarted to my knowledge and no errors are being thrown either.
This is confusing me quite a bit...
Thanks.
// This gets called on page_load
private void checkTimer()
{
if (!parentTimer.Enabled) // If parent timer is not enabled then it is probably the start of a new day (after a night time server backup which kills timers)
{
parentTimer.Interval = 60000; // One minute
parentTimer.Elapsed += new ElapsedEventHandler(parentTimer_Elapsed); // Define what happens when elapsed
parentTimer.AutoReset = true; // Set timer to repeat
parentTimer.Enabled = true; // Start the timer
}
}
protected void btnCancel_Click(object sender, System.EventArgs e)
{
parentTimer.Stop();
...etc...
}
Note: I do not change ParentTimer at all in its elapsed method.
Basically ParentTimer governs a list of ChildTimers. If ParentTimer elapses it checks if one or more of the ChildTimers have elapsed too, if so, there is an event, if not then it resets the ChildTimer and carries on.

My suspicion is it's because the worker process for the page is stopping at the end of the request.
You could try increasing the request time out, but a better question is Can you explain why you're trying to do this ? What is the problem you're trying to solve ?
Remember, that regardless of all the fluff that ASP.Net puts around your code to make you feel comfortable (session state, viewstate etc), a web request is stateless and should be considered as a distinct pass of logic, it's not like a windows application where a background thread of code in your void Main(...) function is constantly running.

A timer is tied to the thread that created it and in the case of ASP.net the thread that handles each page request issued by a given user will change frequently due to the use of worker threads and the thread pool.
Using a timer at page-level simply won't work; you need to be tracking the state at Session-level (tied to the particular user) as your starting point.
In fact, I just wouldn't use timers at all in a web application, because their execution is simply not guaranteed.
If you're using this to run a background task - consider firing up your own worker thread in Application_Start or something like that. The thread will be terminated when the app pool recycles. You should also look at manually shutting the thread down the application is being shut down too.
Be careful with this, however, this thread can't assume it's always the only one running - due to IIS overlapped recycling, when a new one fires up the old one could still be running in the old AppDomain.

Related

Any reason why Winforms Timer does not tick?

I have multiple timers running on my windows app. Each timer_tick runs a code. Right now I am working on two processes.
private async void tmrProcessDelay_Tick
private async void tmrAutopay_Tick
Just recently added the tmrAutopay as an added process so that instead of sequential process, I made them work at the same time. The problem I am having is that I am not able to restart the process of the Autopay.
Timers are declared at the top as an instance when form loads.
private System.Windows.Forms.Timer tmrProcessDelay = new System.Windows.Forms.Timer();
private System.Windows.Forms.Timer tmrAutopay = new System.Windows.Forms.Timer();
tmrAutopay.Interval = 2000;
tmrAutopay.Enabled = false;
tmrAutopay.Tick += new EventHandler(tmrAutopay_Tick);
private async void tmrAutopay_Tick(object sender, EventArgs e)
{
messagebox("tick"); // correcting this one
txtNotes.AppendText("tick");
tmrAutopay.Enabled = false;
// do some code
tmrAutopay.Enabled = true;
}
EDIT: as per Michael Randall suggestion, I tried adding break point at the top. I got the issue. Just on the logic. I just thought that it doesn't start again because "tick" only appends once, so I assumed it only ran once. When I went adding the break point, it ticked again, but for some reason, it did not appendText, reason I did assume things. Going back to the problem, due to the existing logic, after
called tick one - appendtext
enabled = true - ticked but did not append
due to logic, it did not go to enabled = true again
The timer tick only runs after I enabled it the first time, then when its ticks, I set it to false to do some code then start it again after finishing.
I have yet to try this system timer solution, and also saw some post that timers won't run on background process, since I can run it one time, it means it can.. But I just wanna ask before I change timers if there are any reasons why I am having this issue?
if you want to make like background process then you can do window service application and implement more than one timer in that code. I had good working experience with this type of application and I am confident that it will work without any issue with multiple timers. the only thing you need to be careful in code is that in case if some code takes longer than expected and more than timer interval then it will start another thread which could end up as deadlock for that timer or crash the application. Each timer works independently and creates a new thread each time when it ticks.

C# Thread.Sleep(x) or while (DateTime.Now < dateStop)

We have a Win Services with need process a lot of Threads simultaneously and, each thread after complete, need hang-on for while before starting again (the time to hang on is on database configuration).
Everything is fine but in certain odd production environments some Threads has been sleeping for eternity with no occurrence of any kind of errors (Local log and Windows Events). The state of Thread is always in "WaitSleepJoin". The only way to get back is restarting the Services.
So, I did some change in our code:
Thread.Sleep(waitTime);
To:
protected void WaitTime(int millesecs)
{
var dateStop = DateTime.Now.AddMilliseconds(millesecs);
while (DateTime.Now < dateStop)
{
//Hang on
}
}
There is any way better than this??
Use events and set the timeout to be your interval. This has the advantage of providing an option of a clean shutdown of the thread by setting the event.
You should not write the code the second way as the thread Wil be taking too much CPU. Your problem is probably not caused by the sleep.

Threading in Form_Load - Application now hangs suddenly

Sorry for the lengthy post, I just want to illustrate my situation as best as possible. Read the items in bold and check the code if you want the quick gist of the issue.
I use ClickOnce to deploy a C# application, and have opted to have my application check for updates manually using the ApplicationDeployment Class rather than letting it do the update checking for me.
The program is a specialized network scanner that searches for network devices made by the company I work for. Once the main window is loaded, a prompt is displayed asking if the user would like to scan the network. If they say Yes, a scan begins which can take a minute or two to complete depending on their network settings; otherwise it just waits for the user to do some action.
One of the last things I do in Form_Load is create a new thread that checks for updates. This had all been working fine for several months through about 12 releases and has suddenly stopped working. I didn't change the update code at all, nor change the sequence of what happens when the app starts.
In staring at the code, I think I see why it is not working correctly and wanted to confirm if what I think is correct. If it is, it begs the question as to why it DID work before - but I'm not too concerned with that either.
Consider the following code:
frmMain.cs
private void Form1_Load(object sender, EventArgs e)
{
// set up ui, load settings etc
Thread t = new Thread(new ParameterizedThreadStart(StartUpdateThread));
t.Start(this);
}
private void StartUpdateThread(object param)
{
IWin32Window owner = param as IWin32Window;
frmAppUpdater.CheckForUpdate(owner);
}
frmAppUpdater.cs
public static void CheckForUpdate(IWin32Window owner)
{
if (ApplicationDeployment.IsNetworkDeployed) {
Console.WriteLine("Going to check for application updates.");
parentWindow = owner;
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
ad.CheckForUpdateCompleted += new CheckForUpdateCompletedEventHandler(ad_CheckForUpdateCompleted);
ad.CheckForUpdateProgressChanged += new DeploymentProgressChangedEventHandler(ad_CheckForUpdateProgressChanged);
ad.CheckForUpdateAsync();
// CAN/WILL THE THREAD CREATED IN FORM1_LOAD BE TERMINATED HERE???
}
}
When the CheckForUpdateAsync() callback completes, if no update is available the method call simply returns; if an update IS available, I use a loop to block until 2 things occur: The user has dismissed the "Would you like to scan prompt" AND no scan is currently running.
The loop looks like this, which takes place in ad_CheckForUpdateCompleted:
while (AppGlobals.ScanInProgress || AppGlobals.ScanPromptVisible) {
System.Threading.Thread.Sleep(5000);
}
I sleep for 5 seconds because I figured this was happening in a separate thread and it has seemed to work well for a while.
My main question about the above code is:
When ad.CheckForUpdateAsync(); is called from CheckForUpdate does the thread I created in Form1_Load terminate (or might it terminate)? I suspect it may because the subsequent Async call causes the method to return, and then start another thread?
The only reason I am confused is because this method WAS working for so long without hanging the application and now all of the sudden it hangs and my best effort at debugging revealed that it was that Sleep call blocking the app.
I'd be happy to post the full code for frmAppUpdater.cs if it would be helpful.
When ad.CheckForUpdateAsync(); is called from CheckForUpdate does
the thread I created in Form1_Load terminate (or might it terminate)?
If the CheckForUpdateAsync() call is asynchronous then yes, the thread will terminate, no it won't otherwise.
If you suspect the Sleep to have caused the application hang then these two variables AppGlobals.ScanInProgress and AppGlobals.ScanPromptVisible are probably always set to true! You should start looking at the code that is setting them to true and see what is going on there.
In order to avoid an application hang, you could introduce a variable to avoid sleeping indefinitely:
int nTrials = 0;
while ((AppGlobals.ScanInProgress || AppGlobals.ScanPromptVisible) && (nTrials < 5)) {
System.Threading.Thread.Sleep(5000);
nTrials++;
}
// Check the results and act accordingly
I personally do not like using Sleep for thread synchronization. .NET offers a bunch of classes that are perfect for thread synchronization, WaitHandle being one of them.
See this post at Asynchronous Delegates Vs Thread/ThreadPool?
your form load method seems to be doing synchronous work. you mention that you are using clickonce deployment. Has the binary location changed after the previous release or has permissions on this resource changed. Looks like the work (checkupdates) in the Thread is never finishing and is never handed back to the form.
as an immediate fix, I would change the Thread approach to Delegate - if you use delegate, then this becomes less of a customer issue (the form will respond to end user) but the underlying problem remains.
as the next step, i would go through http://msdn.microsoft.com/en-us/library/ms229001.aspx and do the troubleshoot

DispatchTimer - Prevent the tick event to be triggered if the previous tick is still running

In a Silverlight app, I have a block of code that has to run every 500ms. I am planning o use a DispatcherTimer to achieve this (see code below).
DispatcherTimer dt = new DispatcherTimer();
dt.Interval = new TimeSpan(0, 0, 0, 0, 500); // 500 Milliseconds
dt.Tick += new EventHandler(dt_Tick);
dt.Start();
However, it may happen that the block of code takes longer than 500ms to execute (the block of code does some webservice calls). How do I make sure that if a call is currently in progress, the DispatcherTimer doesn't trigger another event? What are the options and what is the best way? Using locks?
The DispatcherTimer only runs on the dispatcher thread - so there's no way you could have two handlers running at the same time. It's possible they'll be queued up and run one directly after another, of course - you should check.
However, you shouldn't be making a web service call in a DispatcherTimer anyway. Do it in a background thread, otherwise you're blocking the UI for updating all the time that you're waiting for the web service. Basically you shouldn't do any long-running work in the UI thread. Use one of the various other timers (e.g. System.Timers.Timer) to regularly perform work on a thread pool thread and use the dispatcher to call back to the UI thread when you've got some data which needs to be displayed on the UI.
Of course, now you've got the potential problem of the new kind of timer firing multiple times concurrently, on multiple threads. One option to avoid this is to set the AutoReset property to false, and just schedule the next timer tick at the end of the current one.
I would say you skip a tick if it takes too long, otherwise you will get a huge queue because of the lock.
So in the eventhandler say:
if(!busy) {
busy = true;
// some code which could take longer than 500 ms
busy = false;
}
In order make the event run successfull without getting a call from your DispatcherTimer again with in the previous tick completes stop the dispatcher timer after entering in to dt_Tick event and at the end of the tick event call the start again which will initializes the IsEnabled of DispatcherTimer again to true.
I don't know if DispatchTimer has any clever way to do this but what I would do in this situation is not to try to get the timer to not fire the event but to get the event to do nothing if it has not finished the previous run.
You can use locks to do this by getting a lock at the beginning of your event handler. If the lock is not available then exit the function (its already running) if you get the lock do the work and then once you've finished the work release the lock.
The method you want is Monitor.TryEnter and you'll want to make sure that you do your error trapping correctly as with any use of locks.

Kill event thread

I have a timer event that fires every second. Sometimes when I exit the program (in the VS debugger), it tells me that the event thread is trying to access an object that no longer exists (because the main thread is over). I tried disabling the event before I exit (UpdateTime.aTimer.Enabled = false;). This cut down the number of times this problem occurs, but it still happens sometimes because the event fires before I can disable it.
Is this a serious problem? Will is haunt me if I don't deal with it?
If yes to the above, how do I kill it?
I ask the second question because I have no reference to the event thread, so I don't know how I can tell it to stop or wait for it to finish.
EDIT: More context. This is a Winform.
Also, I'm not explicitly creating a thread. It's my understanding that a thread is automatically created to handle events.
Creating the timer:
public static void Update(){
System.Timers.Timer aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Enabled = true;
}
Event handler:
private static void OnTimedEvent(object source,ElapsedEventArgs e) {
Form1obj.updateLabel(String.Format("{0}", DateTime.Now.Second),Label1);
}
Closing program handler:
private void Form1_FormClosing(object sender,FormClosingEventArgs e) {
aTimer.Enabled = false;
}
Serious Problem? Probably not, but I don't think a problem needs to be serious to need to be fixed. Warnings should be treated as errors in compilation, for example. In addition, if this is an app sent to clients, showing ugly errors on shutdown is not very professional.
How to solve this depends on how you are setting up the threads ("event thread" does not give enough info about the mechanics). One easy method might be to stall the main thread for a bit when the application shuts down until the threads all return. You have to also stop issuing new threads during this time.
Another possible solution would be to handle how the threads are created so you can shut down the process that fires them. Concepts like ThreadPool come to mind. Also ensuring threads are background threads, explicitly, can help in some situations.
The short answer is nobody will be able to give you a firm "this will fix your issue" answer without some context of what you are doing in your code.
ADDED:
There are a couple of "quick, down and dirty" ways to handle this. Don't have time for full analysis, so see if they work.
Just cure the error by waiting
Add a counter and wait until incremented down
The first thing I would consider is adding a safety net to not update the label when in a shutdown condition. That is regardless of anything else, as that is where your errors are firing. I don't think "main thread is not present" is the core of the issue, but rather this line:
Form1obj.updateLabel(String.Format("{0}", DateTime.Now.Second),Label1);
How can you update something that no longer exists? Yes, it is on the main thread, so technically ...
A simple wait would be something like:
private void Form1_FormClosing(object sender,FormClosingEventArgs e)
{
aTimer.Enabled = false;
Thread.Sleep(5000);
}
Hiding the form is also not a bad idea, so the user does not see this?
If you want to use a more "COM like approach", you can add a counter. Increment on Update() (when the event is fired) and decrement on OnTimedEvent(). Make sure you lock the counter when changing it so you do not end up with two threads changing it at the same millisecond. You can then wait until the counter is 0 to finish form close or application unload.
Once again, these are quick, down and dirty, approaches, but they can save you from the error. I am sure someone with more time can come up with a more elegant solution.
You can close the window as suggested in MSDN - when you set the timer to be disabled during shutdown processing, set a flag that your Elapsed event handler can check to know that no more work is needed.
Elapsed events can occur after the
Dispose or Stop method has been called
or after the Enabled property has been
set to false, because the signal to
raise the Elapsed event is always
queued for execution on a thread pool
thread. One way to resolve this race
condition
is to set a flag that tells the event
handler for the Elapsed event to
ignore subsequent events.
Its hard to give a general awnser to the question if its serious or not, it depends entiry on what the timer is doing. what kind of timer is it? a system.Threading one or one of the UI timers?
If possible try and refactor your code so that you can tell the timer to stop firing, if only for the reason not to confuse the users with an error message. it could be as simple as sharing a variable or (preferably) using a CancellationToken

Categories

Resources