Tutorial :Thread timeout in c#



Question:

I'm new to threading in C#. Is there anyway of setting a timeout for a thread without blocking the calling thread (in C# 3.5)?

If not, is it logical to execute a function using a thread and within that function create a thread and join it to overcome this main thread blocking issue? To illustrate:

Instead of:

Public void main()  {          ...          Thread thrd1 = new Thread(new ThreadStart(targetObj.targetFunc));          thrd1.Start();          thrd1.Join();          ...  }  

Using something like:

Public void main()  {          ...          Thread thrd1 = new Thread(new ThreadStart(middleObj.waiter));          thrd1.Start();          ...  }    //And in the middleObj.waiter():  Public void waiter()  {          Thread thrd2 = new Thread(new ThreadStart(targetObj.targetFunc));          thrd2.Start();          thrd2.Join();  }  


Solution:1

I checked and the simplest and most comprehensive way of doing it was the solution I mentioned in the description of the question. A middle level thread can easily wait for the second thread without any interruption over the main thread; and it can kill the second thread if it does not respond within the required time. That's exactly what I needed. I used it and it worked without a problem.


Solution:2

You can start a System.Threading.Timer for each thread and pass it the thread's ManagedThreadId. Keep dictionaries for the active threads and their timers, keyed by the ManagedThreadId. If a timer expires, use the passed thread ID to abort the thread and kill its timer. If the thread finishes normally, invoke a callback that kills the timer. Here's a simple console example:

using System;  using System.Collections.Generic;  using System.Threading;    namespace ConsoleApplication2  {      public delegate void KillTimerDelegate(int arg);        class Program      {          static Dictionary<int, Thread> activeThreads = new Dictionary<int, Thread>();          static Dictionary<int, Timer> activeTimers = new Dictionary<int, Timer>();          static void Main(string[] args)          {              for (int i = 0; i < 10; i++)              {                  Worker worker = new Worker();                  worker.DoneCallback = new KillTimerDelegate(KillTimer);                  Thread thread = new Thread(worker.DoWork);                  activeThreads.Add(thread.ManagedThreadId, thread);                  thread.IsBackground = true;                    thread.Start();                  Timer timer = new Timer(TimerCallback, thread.ManagedThreadId, 500, 500);                  activeTimers.Add(thread.ManagedThreadId, timer);              }              Console.ReadKey();          }            static void TimerCallback(object threadIdArg)          {              int threadId = (int)threadIdArg;              if (activeThreads.ContainsKey(threadId))              {                  Console.WriteLine("Thread id " + threadId.ToString() + " aborted");                  activeThreads[threadId].Abort();                  KillTimer(threadId);              }          }            static void KillTimer(int threadIdArg)          {              activeThreads.Remove(threadIdArg);              activeTimers[threadIdArg].Dispose();              activeTimers.Remove(threadIdArg);          }      }        public class Worker      {          public KillTimerDelegate DoneCallback { get; set; }          Random rnd = new Random();            public void DoWork()          {              Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + " started");              Thread.Sleep(rnd.Next(0, 1000));              Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + " finished normally");              DoneCallback(Thread.CurrentThread.ManagedThreadId);          }      }  }  


Solution:3

You might also want to take a look at ThreadPool.QueueUserWorkItem() ( http://msdn.microsoft.com/en-us/library/kbf0f1ct.aspx ) which does a lot of stuff for you.

As Brian commented, aborting a thread is usually not a smart thing to do, because it could be in the middle of doing some important stuff at that moment.


Solution:4

See this: http://www.techtalkz.com/c-c-sharp/111717-thread-timeout.html

Check out the TimeSpan method http://msdn.microsoft.com/en-us/library/23f7b1ct.aspx


Solution:5

The easiest thing to do is to call Thread.Join at safe points from your main thread and pass in the amount of time you want to wait for the join to occur.

public static void Main()  {    TimeSpan timeout = TimeSpan.FromSeconds(30);    Thread thread = new Thread(() => { ThreadMethod(); });    thread.Start();    DateTime timeStarted = DateTime.UtcNow;    DoSomeWorkOnThisThread();    // We are at a safe point now so check the thread status.    TimeSpan span = DateTime.UtcNow - timeStarted; // How long has the thread been running.    TimeSpan wait = timeout - span; // How much more time should we wait.    if (!thread.Join(wait))    {      thread.Abort(); // This is an unsafe operation so use as a last resort.    }  }  


Solution:6

"Join member--> Blocks the calling thread until a thread terminates, while continuing to perform standard COM and SendMessage pumping." MSDN website.

thrd1.Join() tell the calling thread to wait until the completion of the thrd1.

My favorite solution is to make a small class which i'm able to control the execution of thread.

public class MyClass      {          private bool _stop;          private Thread _myThread;            public void Stop()          {              _stop = true;              //Will block the calling thread until the thread die              _myThread.Join();          }            public void Run()          {              _stop = false;              _myThread = new Thread(Work);          }            public void Work()          {              do              {                } while (!_stop);          }     }  


Solution:7

Look at WaitHandle.WaitOne() method with the middleObject scheme.

Public void main()  {      ...      middleObj.WaitHandle.Reset();      Thread thrd1 = new Thread(new ThreadStart(middleObj.waiter));      thrd1.Start();      middleObj.WaitHandle.WaitOne(timeout);      ...  }      //And in the middleObj.waiter():  Public void waiter()  {      Thread thrd2 = new Thread(new ThreadStart(targetObj.targetFunc));      thrd2.Start();      thrd2.Join();      this.WaitHandle.Set();  }  

Not sure what would happen to the unfinished thread, though.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »