1

I wrote an ASP.NET system with the Visual Studio 2022 community. But recently a functional module has a strange problem.

Here I have three timing tasks, one is not controllable, and the other two tasks are running normally.

The last time was unable to run in this situation. For example, this task executed systemic logic but did not send messages to users. I did not find related hints in the log.

The following is my code:

   protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        try
        {
            LogFile.WriteError(DateTime.Now + "Start");
            var checkWorkInterval = double.Parse((CachedConfigContext.Current.CheckWorkConfig.Interval * 1000).ToString());
            Timer checkWorTime = new Timer(checkWorkInterval);
            checkWorTime.Elapsed += new System.Timers.ElapsedEventHandler(CheckWorkEvent);
            checkWorTime.AutoReset = true;
            checkWorTime.Enabled = Convert.ToBoolean(CachedConfigContext.Current.CheckWorkConfig.MasterSwitch);
        }
        catch (Exception ex)
        {
            LogFile.WriteError(DateTime.Now + "error" + ex.ToString());
        }
    }
    protected void Application_End()
    {
        LogFile.WriteError("Start 0230");
        System.Threading.Thread.Sleep(5000);
        string strUrl = "http://" + Application["WebApiUri_Authority"].ToString() + "/api/Msg/Post";

        string strRec = HttpClientHelper.PostData("", strUrl, "", "", HttpClientHelper.PostContentType.JSON);
    }

    private void CheckWorkEvent(object sender, ElapsedEventArgs e)
    {
        var time = (Timer)sender;
        DateTime nowDate = DateTime.Now;
        try
        {
            DateTime startDate =CachedConfigContext.Current.CheckWorkConfig.StartTime;//22:00
            DateTime endDate =CachedConfigContext.Current.CheckWorkConfig.EndTime;//23:00
            if (startDate <= nowDate && nowDate <= endDate)
            {
                time.Stop();
                LogFile.WriteError(DateTime.Now + "Start");

                var count = checkworkBll.CheckWorkCreate();
                time.Start();
            }
        }
        catch (Exception ex)
        {
            LogFile.WriteError(DateTime.Now + "error" + ex.ToString());
            time.Start();
        }
    }

After each task stops, I try to restart the program to return to normal. But after a while, it will stop running. I have re -generated Bin files before, will it be caused by this reason?

Pater
  • 13
  • 3
  • 2
    There are no tasks in this code. There's only a single orphaned timer (checkWorTime ) that's eligible for garbage-collection as soon as `Application_Start` exits. `Timer checkWorTime` is a local timer variable. Whatever is stored in there is eligible for garbage collection as soon as it gets out of scope – Panagiotis Kanavos Mar 27 '23 at 13:07
  • 3
    If you want to schedule jobs use a library like HangFire, Quartz.NET etc. [This article](https://www.hanselman.com/blog/how-to-run-background-tasks-in-aspnet) by Scott Hanselman explains the options and why you can't just start a timer or Thread to do work in the background – Panagiotis Kanavos Mar 27 '23 at 13:11
  • I changed the start mode of IIS as the reply said, and my timer task does start. But got new problem again, my timer task stops automatically sometimes. I referenced Quartz.NET as the comments said and everything works fine now, thanks everyone. – Pater Mar 28 '23 at 15:09

1 Answers1

0

I agree with PanagiotisKanavos' point of view. According to the garbage collection mechanism of C#, it is easy for the timer to be recycled. At the same time, he also gave the corresponding reference materials in the comments.

What I want to say here is that in addition to the above situations, it may also be because the application pool is closed or recycled.

There are two startup modes in IIS: OnDemand startup mode and AlwaysRun startup mode. Usually the default startup mode is OnDemand. It is recommended that you change to the AlwaysRun startup mode, and change the idle time to 0, set enable preloading to true, and disable application pool recycling.

You can refer to here for the detailed difference between these two modes.

If it doesn't work please let me know.

sssr
  • 364
  • 1
  • 6
  • 2
    Garbage collection has nothing to do with the startup mode or pool recycling. It runs no matter what. Since the timer is orphaned, it will be GCd sooner or later – Panagiotis Kanavos Mar 28 '23 at 08:06
  • @PanagiotisKanavos Sorry, I have some misunderstandings – sssr Mar 28 '23 at 08:37
  • Take a look at this: [Why does a System.Timers.Timer survive GC but not System.Threading.Timer?](https://stackoverflow.com/questions/4962172/why-does-a-system-timers-timer-survive-gc-but-not-system-threading-timer) An enabled `System.Timers.Timer` is rooted by itself. Even if you abandon it, it will keep ticking until the process is terminated. – Theodor Zoulias Mar 28 '23 at 11:06