1

I have a thread that shoots events to run programs at certain times.

I do want the website to have full control over the process so that is why I built it into the site as a long term thread that loops.

The issue is I scheduled a task to happen at a particular time and it happens almost randomly (maybe when I load the page). It seems as if the web app sleeps all threads until its used or something.

Here is the code:

public void run()
{
    Task.Factory.StartNew(() =>
    {
        while (true)
        {
            var lastDate = InternalEventLogger.GetLastDateTime();
            if (DateTime.Now >= lastDate.AddDays(1))
            {
                System.Diagnostics.Debug.WriteLine(DateTime.Now);
                System.Diagnostics.Debug.WriteLine(lastDate.AddDays(1));
                InternalEventLogger.RefreshLog();
            }
            bool needUpdate = false;
            System.Diagnostics.Debug.WriteLine("this");
            List<Event> tempList = new List<Event>(this.evtList.getList());
            foreach (Event evt in this.evtList.getList())
            {
                if (!evt.status.Equals("success"))
                    continue;
                if (evt.nextRun <= DateTime.Now)
                {
                    var tempEvt = evt;
                    System.Diagnostics.Debug.WriteLine("time to run: "+evt.name);
                    tempList.Remove(evt);
                    tempEvt.nextRun = evt.nextRun.AddMinutes(evt.interval);
                    tempEvt.lastRan = DateTime.Now;
                    tempList.Add(tempEvt);
                    needUpdate = true;
                    if (tempEvt.runLocation != null) 
                    Task.Factory.StartNew(() =>
                    {
                        Process p = new Process();
                        p.StartInfo.FileName = tempEvt.runLocation;
                        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                        p.Start();
                        string output = p.StandardOutput.ReadToEnd();
                        string err = p.StandardError.ReadToEnd();
                        InternalEventLogger.WriteLog(output);
                        InternalEventLogger.WriteLog("// ------------- ERROR -------------- \n" + err);
                        p.WaitForExit();
                    });
                }
            }
            if (needUpdate)
            {
                this.evtList.setList(tempList);
                this.evtList.serialize(ConfigurationManager.AppSettings["xmlEventLocation"]);
            }
            Thread.Sleep(10000);
        }
    }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}

Ran from:

private static void RegisterServices(IKernel kernel)
{
    evtManager = new EventManager(ConfigurationManager.AppSettings["xmlEventLocation"]);
    evtManager.run();
    // Initalize Event Logger
    new InternalEventLogger();
} 

Here is a pic that shows the problem in timing: enter image description here

IIS Settings below
Only at visit does it start the tasks.

enter image description here

VMAtm
  • 27,943
  • 17
  • 79
  • 125
Ya Wang
  • 1,758
  • 1
  • 19
  • 41
  • IIS recycles app pools every 1740 minutes (29 hours) by default http://stackoverflow.com/questions/13386471/fixing-slow-initial-load-for-iis Could this be a cause of your problem? If so you can change this in your app pool recycling settings: http://weblogs.asp.net/owscott/why-is-the-iis-default-app-pool-recycle-set-to-1740-minutes – user1666620 Mar 02 '16 at 15:38

2 Answers2

0

Open that settings dialog in your IIS Manager. Make sure you have:

  1. Start Mode = AlwaysRunning
  2. Idle Time-out (minutes) = 0

for the application pool you are using - test the settings so that you are sure you are editing the correct pool.

If you have this, your application should be running all the time, but there is one more thing - Recycling - at the bottom of that setting dialog, set up your Recycling as you need it. It might be the case that you are OK with the defaults, but if you are not aware of Recycling, it might surprise you, so make sure you understand it and configure the settings as you need it.

Wapac
  • 4,058
  • 2
  • 20
  • 33
  • Disabling recycling work, it may not be the best why of doing things but that is the easy way out for now. Thanks – Ya Wang Mar 21 '16 at 13:25
0

Yes, you are right, the IIS hosting do not stores the threads, as all the Web Application has to do is handle the request and provide the response. If you want to run the task on schedule, you really shouldn't use the web application, as it cancels all the background threads after the response is sent.

I suggest you to change your architecture, and create a Windows service (like daemon) which will start automatically after system boot, and which can much more easily control the event firing.

If for somewhat reason you want a web interface for such method, you can use a WCF binding between your web application and windows service (over TCP/IP or named pipes or whatever), but your approach wouldn't work for Web Application.

I want also to point out that this code:

while (true)

is a bad idea - you should use a CancellationToken for your task in this case.

VMAtm
  • 27,943
  • 17
  • 79
  • 125
  • What is your suggestion about using a thread for user requests to run a program and the scheduled runs be linked to windows task scheduler using an api like http://taskscheduler.codeplex.com/ – Ya Wang Mar 02 '16 at 17:39
  • Yes, you can use something like that – VMAtm Mar 02 '16 at 19:48