简体   繁体   English

C#-当计算花费更多时间时,关闭控制台应用程序

[英]C# - Close console application when calculations take more time

I wrote app that is doing repeatedly some task every minute. 我编写的应用每分钟重复执行一些任务。 Problem is that sometimes ( inner calculations ( because CPU was busy or because of any reasons) take more than 50 seconds, then I have to close app. "App monitor that is independent application will turn it on again" so that is not a problem. I implemented watchdog which can tell me if time is finished and then shut down my app. And my question is if I'm doing it correctly. I test this solution for some time and it looks like working ok. 问题是有时(内部计算(由于CPU忙或由于任何原因)需要50秒钟以上,然后我必须关闭应用程序。“作为独立应用程序的应用程序监视器将再次打开它”,所以这不是问题。我实现了看门狗,它可以告诉我时间是否结束,然后关闭我的应用程序。我的问题是我是否做得正确。我测试了此解决方案一段时间后,看起来工作正常。

Main program 主程序

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AppTimer
{
    class Program
    {
        public static appScheduler ap = new appScheduler();
        static void Main(string[] args)
        {
            Console.WriteLine("Press ESC to stop");
            while (ap.getWatchDogSeconds() < 55)
            {
                if (Console.KeyAvailable)
                {
                    if (Console.ReadKey(true).Key == ConsoleKey.Escape)
                    {
                        break;
                    }
                }
                Thread.Sleep(100);
            }
            Console.WriteLine("Watchdog Fired ....sw finished !!");
            Thread.Sleep(2000);
        }

        /// <summary>
        /// Emulation of long calculation process
        /// </summary>
        public static void doJob()
        {
            Console.Clear();
            Thread.Sleep(5000);
            Console.WriteLine("Busy...");
            Console.WriteLine("WatchDog Seconds : " + ap.getWatchDogSeconds());
            ap.setWatchDogSeconds(40);
            Console.WriteLine("Waiting longer than normal...");
            Console.WriteLine("WatchDog Seconds : " + ap.getWatchDogSeconds());
            Thread.Sleep(5000);           
            Console.WriteLine("Maybe sth is down !! or too busy");
            Console.WriteLine("WatchDog Seconds : " + ap.getWatchDogSeconds());
            while (true)
            {
                Thread.Sleep(200);
            }
        }
    }
}

Below appScheduler class : 在appScheduler类下面:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AppTimer
{
    public class appScheduler
    {
        static readonly object _lockerWD = new object();
        static int minutes = 0;
        static int seconds = 50;
        static int days = 0;
        static int hours = 0;
        private static Task calculationsTask;
        private int watchDogSeconds = 0;
        private int maxSecondsForWatchdog = 50;

        public appScheduler()
        {
            startTimer();
            startWatchdogTimer();
        }

        private void ExecuteSeconds()
        {
            if (seconds == 0)
            {
                executeRepeatdTask();
            }
            calculateTime();
            showTimerScreen();
        }

        private void executeRepeatdTask()
        {
            calculationsTask = Task.Factory.StartNew(() =>
                Program.doJob());
        }

        public void startTimer()
        {
            var timer = new System.Threading.Timer((e) =>
            {
                ExecuteSeconds();
            }, null, 0, 1000);
        }

        public void startWatchdogTimer()
        {
            var timer = new System.Threading.Timer((e) =>
            {
                ExecuteSecondsWatchDog();
            }, null, 0, 1000);
        }

        private void ExecuteSecondsWatchDog()
        {
            Trace.WriteLine("Current amount of WD Seconds : " + watchDogSeconds);
            increaseWatchDogSeconds();
        }

        private void showTimerScreen()
        {
            if ((calculationsTask == null) || (calculationsTask.IsCompleted == true))
            {
                //making watchdog zero if time is running and we are showing it!!
                Console.Clear();
                Console.WriteLine("This is software v1.2");
                Console.WriteLine(String.Format("Current execution time : {0} days : {1} hours : {2} : minutes : {3} seconds",
                        days, hours, minutes, seconds));
                Console.WriteLine("WatchDog Seconds : " + watchDogSeconds);
                setWatchDogSeconds(0);
            }
        }

        private void calculateTime()
        {
            seconds++;
            if (seconds > 59)
            {
                seconds = 0;
                minutes++;
                if (minutes > 59)
                {
                    minutes = 0;
                    hours++;
                    if (hours > 23)
                    {
                        hours = 0;
                        days++;
                    }
                }
            }
        }

        public int getMinutes()
        {
            return minutes;
        }
        public int getWatchDogSeconds()
        {
            return watchDogSeconds;
        }
        public void setWatchDogSeconds(int seconds)
        {
            Monitor.Enter(_lockerWD);
            watchDogSeconds = seconds;
            Monitor.Exit(_lockerWD);
        }

        public void increaseWatchDogSeconds()
        {
            var seconds = getWatchDogSeconds();
            setWatchDogSeconds(seconds += 1);
            if (seconds > maxSecondsForWatchdog)
            {
                Trace.WriteLine(string.Format("More than {0} seconds!", maxSecondsForWatchdog)); ;
                Environment.Exit(0);
            }
        }
    }
}

I do a great deal of workflow type tasks every day. 我每天都会做大量的工作流类型任务。 I have tried to kick off jobs in the past the way you have here. 过去,我曾尝试过像您在这里一样开展工作。 The only time I use Thread.Sleep is to simulate some long running process in a test environment. 我唯一使用Thread.Sleep的目的是在测试环境中模拟一些长时间运行的过程。 I would look into using SetTimer. 我会考虑使用SetTimer。 Also using Thread.Sleep in a loop is not going to give you accurate results. 同样在循环中使用Thread.Sleep并不会给您准确的结果。 Now, that being said, keeping this running is going to be tricky. 话虽如此,保持这种运行状态将非常棘手。

Ultimately kicking off jobs on a regular basis is a breeze if you have an SQL server and can set the call up in an SSIS package. 如果您有一台SQL Server,并且可以在SSIS程序包中进行调用,那么最终定期地开始工作很容易。 Especially if you are are trying to do this in a web application which might just stop running after a period of time. 特别是如果您尝试在可能会在一段时间后停止运行的Web应用程序中执行此操作。 Good Luck 祝好运

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM