Answered multithreading with timeout

  • Wednesday, January 18, 2012 11:06 AM
     
      Has Code

    Hello all,

    my requirement is like below;

    i have one function which contains no. of tasks and no. of thread (function (var noOftasks,var noOfThread)); which will be called from outside or say from another app.

    when this function calls i create noOfthread and assign task to each thread one by one, if all thread is busy then wait for any thread to be free and then again assign task( if any remaining) to it.

    now i also want to set timeout that if any thread running out of time then it will be aborted

    because main thread is working continously to check free thread and assign task, i can not rely on Thread.Join(timeout) and make thread aborted according to that.

    how can i achieve same? below is code snippet
    public class TaskA
    {
    
        public List<TaskProcess> ProcessTasks(List<TaskProcess> ListOfTaskProcess, int NoOfThreads)
        {
            try
            {
                Thread[] _threadPool = new Thread[NoOfThreads];
    
                foreach (var _task in ListOfTaskProcess)
                {
                    Thread _Thread = null;
    
                    while (true)
                    {
                        _Thread = GetFreeThread(_threadPool);
    
                        if (_Thread != null)
                        {
                            break;
                        }
                        else
                        {
                            Thread.Sleep(1000);
                        }
                    }
    
                    if (_Thread != null)
                    {                    
                        _Thread.Start(_task);
                    }
                }
    
                foreach (var _Thread in _threadPool)
                {
                    if (_Thread.IsAlive)
                    {
                        _Thread.Join();
                    }
                }
    
                return ListOfTaskProcess;
            }
            catch (Exception)
            {
                return ListOfTaskProcess;
            }
        }
    
        private Thread GetFreeThread(Thread[] p_ThreadPool)
        {
            try
            {
                foreach (var _thread in p_ThreadPool)
                {
                    if (_thread == null || (_thread.IsAlive == false && _thread.ThreadState != ThreadState.Running))
                    {
                        return new Thread(doTask);
                    }
                }
    
                return null;
            }
            catch (Exception _Exception)
            {
                
            }
        }
    
        private void doTask(object _task)
        {
            try
            {
                _task.status = "In Progress";
    
                /* do task process here*/
    
                _task.status = "completed";                
            
            }
            catch (Exception _Exception)
            {
                _task.status = "Failed";
            }
        }
    
        public class TaskProcess
        {
            /* other properties */
            public string status { get; set; }
        }
    }
    


    please help me to do it.

     

    Thanks,

    Vishal Parekh

All Replies

  • Wednesday, January 18, 2012 11:58 AM
     
     Proposed Answer

    instead of managing the thread by yourself, i will suggest you to use the ThreadPool that comes with the .net framework.

    The only thing you do is just queue work items, then the thread pool will schedule it to execute. 

    http://msdn.microsoft.com/en-us/library/3dasc8as(v=VS.80).aspx


    Johnny
    • Proposed As Answer by Shweta Jain Wednesday, January 18, 2012 12:00 PM
    •  
  • Thursday, January 19, 2012 6:45 AM
     
      Has Code

    Thanks Johnny,

    yes threadpool is better,

    but how can i set timeout for each thread? ; as i want that after particular time if thread is not completed then i need to abort that thread .

    i change above code snippet; i use Timer to make timeout for each thread

     

    .....
    
     if (_Thread != null)
     {
    
                            TimerCallback tcb = AbortThread;
    
                            Timer _Timer = new Timer(tcb, _Thread, ThreadTimeOut, Timeout.Infinite);
    
                            _Thread.Start(_task);
     }
    
      private static void AbortThread(object _Thread)
            {
                try
                {
                       if (_Thread.IsAlive)
                       {
                           _Thread.Abort();
                       }
                 }
                 catch(Exception)
                 {
            
                  }
            }
    


    is it proper way to do it?

     

    Thanks,

    Vishal Parekh

     

     

  • Thursday, January 19, 2012 12:40 PM
     
     Answered

    Hi Vishal,

       I will use WaitHandler, and ManualResetEvent, something like the following....

       it doesn't control the timeout of each single thread, but it just control the overall time. the waithandler will wait all the waithandler to get a signal for 60 seconds, if it timeout, then it will move on..

    public class TaskItem

        {

            private ManualResetEvent _mre = null;

            public TaskItem(ManualResetEvent mre)

            {

                _mre = mre;

            }

            public void DoTask()

            {

                Console.writeline("Do task");

                Thread.sleep(1000);

                _mre.set();

            }

        }

     

        public class MainClass

        {

            public MainClass()

            {

     

            }

            public void DoTest()

            {

                var lst = new List<TaskItem>();

                var lstRestEvent = new List<ManualResetEvent>();

                for (int i = 0; i < 10; i++)

                {

                    var re = new ManualResetEvent();

                    var ti = new TaskItem(re);

                    lst.add(ti);

                    lstResetEvent.add(re);

                    ThreadPool.QueueWorkItems(ti.DoTask);

                }

                //Wait all the thread to exit for 60 seconds.

                WaitHandler.WaitAll(lstResetEvent.ToArray(),60*1000);

            }

        }

        Hope this can meet your requirement.

     


    Johnny