• Some users have recently had their accounts hijacked. It seems that the now defunct EVGA forums might have compromised your password there and seems many are using the same PW here. We would suggest you UPDATE YOUR PASSWORD and TURN ON 2FA for your account here to further secure it. None of the compromised accounts had 2FA turned on.
    Once you have enabled 2FA, your account will be updated soon to show a badge, letting other members know that you use 2FA to protect your account. This should be beneficial for everyone that uses FSFT.

Timers and threading in asp.net (c#)

PrincessFrosty

Supreme [H]ardness
Joined
May 6, 2009
Messages
5,905
Hi again everyone :)

I've come across an interesting problem with a website design, I've found that shared hosting for ASP.NET based websites with a MySQL database don't usually offer support for scheduling stored procedures, mostly due to security.

So I've had to be a bit inventive, I've created a timer in the Global.asax file in the application start which is run when the webserver comes up for the first time, and this starts an asynchronous thread which I want to run a set of stored procedures every hour. So i've used the following code:

Code:
    // create new timer
    private void CreateTimers()
    {
        System.Timers.Timer WebServiceTimer = new System.Timers.Timer();

        WebServiceTimer.Enabled = true;
        WebServiceTimer.Interval = (60000 * 60); // currently 1 hour

        WebServiceTimer.Elapsed += new System.Timers.ElapsedEventHandler(WebServiceTimer_Elapsed);
    }

I just have code in the WebServiceTimer_Elapsed to connect to the database and call the stored procedures in mysql.

Now this actually works, I've read in many places that it's not supposed to and that ASP.NET doesn't actually support this sort of stuff, but with my development testing and live testing this actually runs in the background independently of anyone browsing the website and does some basic incriments of data in my database.

My problem is that I cannot find a way to reference this asynchronous thread once it's started. I've built an admin page for my website which I want to set an enabled/disabled button for this thread and put in a label so I know if it's currently running or not (or was running when the page loaded). So basically I want to be able to determin if this is currently running and then stop/start it with the click of a button.

Can anyone help me out? I've looked this up a lot and cannot find ASP.NET specific examples because threading isn't something you typically use with ASP.NET as I understand it.
 
Finally worked something out!

Just in case its helpful for anyone else, you can create the timer as its own class in the App_Code folder, make it static then you can reference it from your websites code behind on any page, essentially I've created an asynchronous service that runs on my website which can run stored procedures at intervals, then I can just start/stop that from my admin page whenever I need it, very handy!

A really good reference - http://dotnetperls.com/timer
 
Glad you found a solution.

Be aware, though, that your timer is still executing under the ASPNet worker process, and can have moments where it is not running or the timer gets reset depending on web server actions (ex: IIS reset). If you need something more reliable to scheduled intervals, then consider migrating the logic to a Windows service
 
Glad you found a solution.

Be aware, though, that your timer is still executing under the ASPNet worker process, and can have moments where it is not running or the timer gets reset depending on web server actions (ex: IIS reset). If you need something more reliable to scheduled intervals, then consider migrating the logic to a Windows service

Well the whole point of doing this was because I'll be using a cheaper shared hosting solution where you're not allowed to install windows services or use scheduling due to security reasons.

I've actually ran into a problem with this now, I start the timer and set the values for iteration from a admin page just fine and it executes on the interval I set and incriments my database values correctly. However it lasts for almost exactly 20 minutes on the nose before it just stops running, at the moment it set to iterate at 1 minute intervals and increase values in the database by 1 and i get to 20, sometimes 21 and it basically stop working....

I read in an example that harsh garbage collection could stop these timer threads if they go on for long enough and so used:

GC.KeepAlive(Timer);

But that's not helped either, it's still only lasting 20 minutes each time, it's really irritating!
 
But that's not helped either, it's still only lasting 20 minutes each time, it's really irritating!
Contact your shared hosting provider, and ask what the Session threshold is. I'm guessing they'll say it's ~20 minutes.

Might also be good to ask when and how often the ASPNet worker pool is cycled.
 
Good advice, I actually had someone else advise me theres an idle timeout setting for the application pools in IIS, and that's default 20 minutes, I changed that on my test server to 5 minutes and I only got 7 iterations of the procedure at 1 minute timer interval, so it's definately that value.

I guess I have 2 options with this route, either raise the session threshold to something massive in the order of months, I have no idea what sort of effects that will have on the website.

Or try and find a way to keep that thread alive, afterall it's only suppose to end "idle" threads...by idle they must mean there's no activity between that thread and the user, because it's definately calling my stored procedure every x many minutes, even when x = 1 minute it still gets cleaned up.
 
Ah it seems im not the first person to run into this problem, and for the same reasons as well. This has some helpful information.

http://www.west-wind.com/WebLog/ShowPost.aspx?id=67557

It's possible to ping your own site and simply it serving up requests (even if it has nothing to do with the timer) keeps it alive. It wont quite work for me 'cause I need to send every hour or so and cant have the keep-alive ping in the timer end event.

What Im going to try is having 2 timers, a keep alive one running pings every 5 mins and another worker timer running the actual stored procedures. Will report back on great success or epic fail :p
 
This sounds maintainable given your situation. Thanks for the link; Rick Strahl's definitely had some interesting posts on problems and solutions/workarounds in his career.
 
OK i've been testing this, so far the only problem has been that the webserver cannot reach it's own external address, it's hosted on my PC at home for development and if I try and browse my own site it doesn't work, and neither does it trying to ping itself.

The work around is to create a local binding for the website, something like "localhost" and point it to the LAN IP of the webserver rather than the external IP, this works in my testing.

Now I just have to wait for a reply from my provider to see if they're willing to create a 2nd binding for the website using the local address, I have a funny feeling they'll say no. I have a backup plan though, it should work fine accessing it through a web proxy, if you visit somewhere like hidemyass.com and then browse your site you can grab a URL for that page and probably use that.
 
Sounds like a rule being enforced in the firewall, which might not get removed for a shared hosting account. You may need to come up with a third option in the (likely) case the firewall rule and your alternative idea get rejected. One option is to setup a local Windows service to create a HTTP Request to the webserver to keep IIS and ASPnet session alive. Such a service would need to be hosted locally, but it's one idea. There are even some apps that will regularly ping or do a simple HTTP connect-and-fetch; the app names escape me right now, I'll post if I remember any.


Edit: Remembered the term... it was "keep alive website". Simple phrase, yes; I just couldn't remember it earlier. Still can't think of any names to recommend, but at least that gets you something to Google. Your webhost may even offer this service, but likely with an extra fee. Worth investigating, though.
 
Last edited:
Well my development environment is on my own PC/network so I know theres no rules on the firewall stopping it, it's just not routing correctly because of the way it's set up, I think it's just inherent with hosting the site behind a router/NAT, but the local address works fine.

I actually did consider a website to basically check the status of the pages, I signed up for some free ones but they would only check every 30 minutes which is too slow to avoid timeout, unless I use a whole bunch of them and hope they don't sync up too closely etc etc, a bit unreliable.

A widows service is the best solution, but the whole reason I've created my own one is because they're not allowed in shared hosting packages since you don't have access to the whole machine as you're sharing it with several other websites.

Remember that the top level problem here is not being able to schedule stored procedures (or anything in fact) within a shared hosting environment, if I could run windows services I'd simply use a scheduler to begin with and avoid this rubbish.

Actually I'm kind of glad that I was forced into this route because now I have a full admin panel I built which allows me control over my running servies and I can alter the values for the timer repeat rate and the values passed to the stored procedures, all from within the site itself.
 
Overall this looks like it was a good springboard topic to sink your teeth into some new concepts and implementation ideas, and I think you've found a good option for all of the considerations and limitations of this situation.


To clarify my earlier comments...
As for the Windows service idea, I suggested that you could build and run it on a local box (not the webhost), and use that Windows service to ping and keep the remote website alive. One approach could be similar to this DotNetNuke sample, but obviously doesn't have to be as involved. However, that example does give the high-level ideas.
Regardless, I'm glad you got this worked out and think you've come ahead with the tailored solution. Good work!
 
Thanks, yeah I've been testing and it's been running for a few days now so seems at first glance to be working.

I'm actually building a website based game (MMO style) and this stuff is to increment the amount of action points people have every hour and also the same with hitpoints so everyone has a natural regen over time. I'm almost at a point where I can let everyone take a look and test the basic features :)
 
Bugger...seems to have run 27 hours at 1 increment per hour and now stopped...

Anyone know what else might be stopping this code?
 
Tough to say. Might want to add some error handling and trace logging for a while; SMTP message might be your only method possible. Aside from checking with tech support at the webhost to identify scheduled events (ex: app pool resets, scheduled maintenance, etc.) as a contributing cause, this may involve posting some code.

Are you even able to restart the code's execution?
 
Yeah, again this is on my own test system so I have full control over IIS, I'm not that familiar with error handling, I do have a try catch already on the functions inside the classes I've made for the "keepalive" and "worker" processes but dont do a lot with them.

I'll update tomorrow when I'm less drunk :)
 
I think trace logging is closer to what you'll want on getting intuitive feedback for these kinds of problems. MSDN has a simple example.

Perhaps you'd take the above approach, or even a simple static StringBuilder object with appended messages, and periodically email it to yourself or show it on screen through your custom control panel. Just tossing some ideas out there, hopefully enough to get you on a path.
 
Thanks again for the advice, I looked at that MSDN article, I'm fairly new to tracing although I have seen it before in other projects.

The main problem is this timer thread gets started async with the site, it doesn't run as the code behind for a page so I can't really enable tracing and get output, the closest thing I could do is add the tracing code to the admin page but this only starts/stops the timer, it doesn't actually run in that page.

I think I need to look into the IIS settings a bit more, something is definately killing that thread.
 
This really is developing into a very educational and investigative topic for you!

Generally speaking, I think your next step is going to be multi-faceted where you'll be tossing out tracing and stepping comments -- with timestamps -- at various locations in your web app. The feedback would be compared against known IIS restarts, app pool restarts, user signons, user session expiration, etc. Getting a little more specific, some trace logging code in your admin page, the Global.asax file, and your user login page would really help give some good information to cross-reference against any details obtained from a tech support ticket or previous information sent from your webhost.


Edit: Thinking a little more about this, you may ultimately decide that persisting is not feasible with the shared hosting configuration. You may need to revisit the "keep alive" option with a local service/application that keeps the remote website "alive". But first see what evidence you can dig up from the above suggestions.
 
Last edited:
Back
Top