C# Wait for all threads completed with timeout

By admin - Last updated: Friday, July 31, 2009 - Save & Share - One Comment

We only want to do something after all threads finish their work. The advantage is that all the threads can work simultaneously while each of them has no dependency to the other. Typically, I found it improves efficiency when making call to the remove webservice.

For example, there is a web service operation called getProductById(int id), the problem is the getProductById API only allows you to pass in single Id at a time. When at client side, you need to fetch a list of products at the same time, in this case, we can make each thread to retrieve one product from the service and merge all the result after all threads complete.

Here is the extention method “WaitAll” for generic Thread IEnumerable object,

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

namespace Auva.Core.Utilities
{
    /// <summary>
    /// Contains thread utilities.
    /// </summary>
    public static class ThreadUtil
    {
        /// <summary>
        /// Delegate that will be called after thread timeout.
        /// </summary>
        public delegate void ThreadTimeoutHandler(Thread thread);

        /// <summary>
        /// Waits all threads with timeout defined.
        /// </summary>
        /// <param name="threads">The threads.</param>
        /// <param name="timeoutMilliSeconds">The timeout milli seconds.</param>
        /// <param name="threadTimeoutCallback">The thread timeout callback.
        /// e.g. perform Abort on thread in the handler</param>
        /// <returns>Threads which were timeout.</returns>
        public static IEnumerable<Thread> WaitAll(this IEnumerable<Thread> threads,
                                                     double timeoutMilliSeconds,
                                                     ThreadTimeoutHandler threadTimeoutCallback)
        {
            if (threads==null)
            {
                throw new ArgumentNullException(“threads”, “threads must be defined.”);
            }

            // caculate completion time
            DateTime completionTime = DateTime.UtcNow
                                                              .AddMilliseconds(timeoutMilliSeconds);

            // prepare a list for storing timeout threads
            List<Thread> timeoutThreads = new List<Thread>();

            // join each thread with a timeToLive timeout
            foreach (Thread thread in threads)
            {
                // caculate completion time
                TimeSpan timespan = completionTime – DateTime.UtcNow;

                // time left before timeout
                double timeToLive = timespan.TotalMilliseconds;

                // join the thread with time left
                if (!thread.Join(timeToLive > 0 ? Convert.ToInt32(timeToLive) : 0))
                {
                    timeoutThreads.Add(thread);
                    Debug.WriteLine(string.Format(“Thread {0} timeout.”, thread.Name));

                    // callback, most likely, the callback will abort the thread
                    if (threadTimeoutCallback != null)
                    {
                        try
                        {
                            threadTimeoutCallback(thread);
                        }
                        catch (Exception x)
                        {
                            //silently handle the exception from callback
                            Debug.WriteLine(x.Message);
                        }
                    }
                }
            }

            return timeoutThreads;
        }
    }
}

You might have notice, WaitAll also allows you to define the timeout, the method will invoke threadTimeoutCallback if a thread exceeded the timeoutMilliSeconds defined. This will basically give caller a chance to abort long running threads so that WaitAll will have a time to finish rather than an endless process.

Here is some code for testing it.

[Test]
        public void WaitAllTimeout()
        {
            // initialize all threads
            List<Thread> list = new List<Thread>();
            for (int i = 0; i < 5; i++)
            {
                Thread thread = new Thread(Worker);
                thread.Name = “test” + i;
                list.Add(thread);
                thread.Start();
            }
            // start up all the threads by invoking the extension methods
            list.WaitAll(5000, delegate(Thread thread)
            {
                // this will be called when the checking thread is timeout
                Console.WriteLine(“TimeoutCallback thread: {0}”, thread.Name);
                thread.Abort();
            });
        }

        // the thread worker method
        public void Worker()
        {
           // do some work  with random duration
        }

Occasionally, I found the thread is not being timed out for the given timeout value, normally a few milliseconds after, this is due to .net internal implementation of thread.Join(int timeToLive) that not being timed out strictly by the given value.

Please log a comment if you found bugs or some ideas of improving it. Thanks for Sharing.




Posted in Code Notes • Tags: Top Of Page

One Response to “C# Wait for all threads completed with timeout”

Comment from misterG
Time August 8, 2009 at 4:38 am

please add the following line:

int timeout = 10000;

before this line:
list.WaitAll(timeout, delegate(Thread thread)

Write a comment


Captcha: 8 + = fourteen