Reputation: 793
I recently was designing a server that used Timers to monitor users that are logged into the system and do something after a given amount of time of inactivity. I am using .NET and IIS to manage the server. When I got the server reviewed I got lots of comments about not using timers in a .NET server. A lot of the reasons that were given were that servers should be simple and not have processing that would need a timer. This doesn't make sense to me as depending on the complexity of the server there may be processing that needs to be done. I am curious if there are other reasons that having a Timer on your server would be a bad idea?
Upvotes: 2
Views: 1659
Reputation: 511
For timers in my systems I tend to store the time logged in at and revalidate the users token as the make requests or anything else based on that time recorded. Pretty simple to go from there. It is possible to employ timers but you have to make sure it's entirely necessary. Client side is sometimes my best option so that the server can adequately handle requests and finish them when needed. Keep the load down to a minimum.
Upvotes: 0
Reputation: 3129
First, you need to be aware that IIS may shutdown your application if it goes idle or for some other reasons (for example your application starts throwing exceptions successively). In that case all your timers would be disposed.
Second and more importantly timers are not zero cost. You probably want to execute some function when a specific time is elapsed, and yes, Sytem.Timers.Timer can do that, but with an overhead.
If you want to simulate 100
concurrently handled Timer, each with a 100 Ms
processing time:
Starting timers in 3 seconds...
Timers are all done in 1217 ms.
Press any key to continue . . .
The code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Timers;
namespace TimersTest
{
class Program
{
private static int ConcurrentTimerCount = 100;
private static int Counter = 0;
private static object SyncObj = new object();
private static ManualResetEvent Done = new ManualResetEvent(false);
static void Main(string[] args)
{
var timers = new List<System.Timers.Timer>();
for (var i = 0; i < ConcurrentTimerCount; i++)
{
var timer = new System.Timers.Timer(3000);
timer.Elapsed += TimerElapsed;
timers.Add(timer);
}
var stopwatch = new Stopwatch();
stopwatch.Start();
Console.WriteLine("Starting timers in 3 seconds...");
timers.ForEach(t => t.Start());
Done.WaitOne();
stopwatch.Stop();
Console.WriteLine("Timers are all done in {0} ms.", stopwatch.ElapsedMilliseconds - TimeSpan.FromSeconds(3).TotalMilliseconds);
}
private static void TimerElapsed(object sender, ElapsedEventArgs e)
{
// Simulate 100 ms processing time.
Thread.Sleep(100);
lock (SyncObj)
{
Counter += 1;
if (Counter == ConcurrentTimerCount)
{
Done.Set();
}
}
}
}
}
Upvotes: 0
Reputation: 127543
IIS Shuts down app domains that don't have active requests going to it. This would kill your timers so they would never run.
If you need any kind of long running process you either need to use a library that tricks IIS to run longer without shutting down a app domain or moving the long running code in to a separate Windows Service instead of being in process in IIS.
Upvotes: 0
Reputation: 62260
used Timers to monitor users that are logged into the system and do something after a given amount of time of inactivity.
If I understand your question correctly, you could use Global.asax's Session_End event.
Session_End event is raised automatically when session expires or app pool recycles on a schedule.
If you want to get user's information, you will need to save them inside Session as soon as user successfully logins.
private void Session_End(object sender, EventArgs e)
{
// Code that runs when a session ends.
// Note: The Session_End event is raised only when the sessionstate mode
// is set to InProc in the Web.config file. If session mode is set
// to StateServer or SQLServer, the event is not raised.
var userName = Session["UserName"];
var sessionId = Session.SessionID;
}
Upvotes: 3