locked
Help with Thread Timeout Calculations RRS feed

  • Question

  • User964056028 posted

    May I prefix this with the following:  I am just starting to think about this and am just bouncing ideas around - currently you can think of this as pseudo code - I am absolutely sure this is a piece of work that will take many iterations - and I am not an expert in this area which is why I am posting it here and trying to get others to comment on my ideas, and to come up with better ones!!  ;-)  May I also thank you all for any time you spend looking at this and helping me to come up with a better way of doing things!

    Objective:

    What I am trying to achieve is a way to measure time spent within an "aws session" by all the subtasks in that particular session in order to determine when the aws timeout is about to throw my web services out because the overall "wall clock time" has exceeded 30 seconds.  Rather than have aws time out my session I want my services to gracefully timeout themselves.  I will use the ThresholdReached method to do the graceful timeouts.

    However, this is an environment where a single "aws session" ( I use that term loosely) can consist of many operations (mainly calls to a number of web services - I will call these SubTasks) some of which are synchronous, some of which are async..  in a multi-threading environment..

    namespace MSollicito.Api.Main
    {
      public class HourglassContainer : IContainer  //extend IContainer used elsewhere in app
      {

           // constructor here?

            public HourglassContainer()
            {
                base();  //look at what the container constructors take in as params????

               //not sure if I need a TimeManager in my container or not??

                builder.Register(c =>
                {
                    var timeClient = c.Resolve<ITimeClient>();
                    return new TimeManager(timeClient, APIAuthenticationConfig.Settings.Username, APIAuthenticationConfig.Settings.Password);
                }).As<ITimeManager>().SingleInstance();

            }



        private int _globalTimeValue = 30; //defaults to 30 at beginning (AWS max timeout), contains time remaining for this aws session

        private Object timeLock = new Object(); 

        //this will hold the time remaining for processing
        public static int GlobalTimeValue
        {
            get
            {

                return _globalTimeValue; //would we need read lock too??
            }
            set
            {
                lock (timeLock)
                {                 
                    _globalTimeValue =  value;
                    if (_globalTimeValue == 0)
                    {
                        //fire event letting all threads that need to be notified that they have timed out
                        ThresholdReached();
                    }
                }
            }
        }

        private int _globalSubTasks = 0;  //default to 0

        private Object taskLock = new Object(); 

        public static int GlobalSubTasks
        {
            get
            {

                return _globalSubTasks; //would we need read lock too??
            }
            set
            {
                lock (taskLock)
                {        
                    _globalSubTasks =  value;
                }
            }
        }

        private int _globalTaskTimeForSubTask = 5; //default to 5

        private Object taskTimeLock = new Object(); 

        //its a good idea to add as many GlobalSubTasks as you can before getting TaskTimeForSubTask
        public static int TaskTimeForSubTask
        {
            get
            {
                if (GlobalTimeValue > 0 && GlobalSubTasks > 1)
                {
                    _globalTaskTimeForSubTask = Math.Round(GlobalTimeValue / GlobalSubTasks);
                }
                else
                {
                    _globalTaskTimeForSubTask = 5;
                }
                return _globalTaskTimeForSubTask; //would we need read lock too??
            }
            set
            {
                lock (taskTimeLock)
                {        
                    _globalTaskTimeForSubTask =  value;
                }
            }
        }

        // Create new timer on the main thread
        private System.Timers.Timer TTTimer = new System.Timers.Timer();

        public void StartTiming()
        {

            // Begin timing.
            this.TTTimer.Interval = 1000; //1 sec
            this.TTTimer.Elapsed += new System.Timers.ElapsedEventHandler(TTTimer_Elapsed);
            this.TTTimer.Start();
        }

        void TTTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            string message = string.Format("Tick Generated from {0}", Thread.CurrentThread.Name);

            Console.Write(message);

            this.Dispatcher.Invoke((Action)delegate()
            {
                GlobalTimeValue--; //take one second off of the remaining time
            });
        }

        private Object subTaskAdd = new Object();

        //adding a new task means adding one to total globalsubtasks and finding a new value for TaskTime for the new task
        //this must of course be thread safe!
        public void NewTask()
        {
            lock (subTaskAdd)
            {

                GlobalSubTasks++;

             }

        }

        private Object completeTaskAdd = new Object();

        public void CompleteTask()
        {
            lock(completeTaskAdd)
            {
                GlobalSubTasks--;

            }
        }

        public event EventHandler ThresholdReached;

        protected virtual void OnThresholdReached(EventArgs e)
        {
            EventHandler handler = ThresholdReached;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        //... and so on...

        // public and private methods here...
      }
    }

    I am very hopeful that I will get a lot of feedback and suggestions to help me come up with a good architecture for this.  If anyone knows of a piece of code that already does this kind of work or a pattern that exists already, please feel free to point that out - I am not about re-inventing any wheels that should already exist!

    Thanks so much!

                                                   

    Monday, March 6, 2017 6:42 PM

All replies

  • User-359936451 posted

    Well, I'm not sure I understand exactly what you are trying to do. Either the service is working or its not, i.e. its waiting. If there are a set number of actions that need to happen or should happen, then why not keep a list. and a time stamp from the beginning of the connection until the deadline. You can then check the elapsed time, and the list. Post a time for each even completed, I think you called them subtasks. If the time lapse from the past subtask is too long, shut down the service.

    Hope this helps.

    Tuesday, March 7, 2017 8:16 PM
  • User964056028 posted

    Thanks.. however, sorry if I am not making myself clear -  the issue is that BEFORE I start each thread I need to give it a timeout value so that it knows when to gracefully time itself out.. so it will always be a guess but I want it to be as educated a guess as possible.. which is why I thought the best way would be to see how much time there is left until the deadline and divide that by how many threads are still running and then give the new thread that number as a timeout value?  Does that make sense?

    Wednesday, March 8, 2017 5:48 PM
  • User475983607 posted

    Assign an ID when the a thread is the first to open a Session and log the time.  Register each new thread that uses the same Session with the ID.

    The AWS documentation seems rather clear and provides utilities for handling Session.  You might consider visiting AWS support as they are problem better equipped to field question about their services.

    Wednesday, March 8, 2017 6:36 PM
  • User-359936451 posted

    Well, I am not sure that you are trying to calculate a red herring. I don't know what is expected of the actions each thread will perform, but I don't think that the calculation provides any valuable new deadline. say 12 are still running, what if they all end (or most end) right after the calculation, will the new thread even have enough time to finish what it needs to do?

    The only way I could see making an educated guess about when to time out the thread would be to first have some information about how long it needs to be open to do what it is supposed to do.

    Or, if you are simply trying to cycle threads, then you should probably use a set interval, and restrict how many you open. Too many might slow down the overall processing, server could likely restrict how many you get anyway.

    Or, you might want to maintain an average of how long each thread stays live. That average could become your starting time out for future threads.

    Just some ideas.

    Wednesday, March 8, 2017 6:36 PM
  • User753101303 posted

    Hi,

    If previous answers are not helping we are likeky still missing some more general context.

    For now my understanding is that you are writing a web service (hosted by AWS ?) that will itself call other web services and that it has 30 seconds maximum to complete all its work while behind the scene you are calling quite a number of slow running web services ? For some services you can cell them async. For some other you need to wait a response that you'll use then perhaps for another call ? And so your plan is to give each call a slice of those 30 seconds ?

    Knowing the particular service you are trying to use might also perhaps help. Also a forum for this service might be better (it might involve rather functionnality brought by this service rather than really ASP.NET side knowledge).

    Wednesday, March 8, 2017 6:57 PM
  • User964056028 posted

    Thanks everyone for your help.  You can just think of it as a web service that contains a number of threads, each one has to be finished before the "aws timeout" time of 30 secs.  The fact that it is using aws is irrelevant apart from the timeout time of 30 seconds I believe.  Some threads will be done in parallel and some have to wait for others to finish yes.

    Thanks for all your help in advance

    Wednesday, March 8, 2017 11:11 PM
  • User-2057865890 posted

    Hi Msollicito,

    In the case of asynchronous requests, it is the responsibility of the client application to implement its own time-out mechanism. Please see the complete example on msdn.

    Best Regards,

    Chris

    Wednesday, March 15, 2017 8:03 AM