Solved

Challenging Multithread Question 500points

Posted on 2004-10-07
5
231 Views
Last Modified: 2010-04-15
I am creating a Multithreaded C# Application.  The application will query a database for "jobs" to execute.  If it finds available jobs it will create a new "Job Object" (based on parameters supplied from the dataset returned from the query) and a  fresh worker thread for each job to be run.  This all works great.  I know that when the method (doSomeWork in the below example)  that the new thread calls exits the thread terminates.
Thread workthread = new Thread(new ThreadStart(doSomeWork));

What I need to accomplish is keeping track of all currently running threads.  When the thread is created it will increment an int variable, and decrement that variable when the thread exits.  I would also like to uniquely identify each thread.  So I can have, say a list box on a Winform showing currently executng threads.  So, essentially how do I monitor/track/label existing threads?

500 Points for some help.
0
Comment
Question by:mandalorian4
  • 2
  • 2
5 Comments
 
LVL 6

Accepted Solution

by:
boblah earned 500 total points
Comment Utility
Hi mandalorian4,

Create a singleton object (Design patterns, GoF) - basically an object that has a single instance that all the different threads can access.

Have methods for threads to register themselves with it, and notify it when they are finished. (be careful the finish call is robust, with error trapping and finally etc)

The front end can then interrogate the singleton for the current status.

Below is an example of a singleton I wrote once for a situation where various different threads were accessing a printer resource for which we only had five licenses - so only five threads at any one time could do the printing.

It should be reasonably clear how to modify it for your situation, although it does contain a bunch of stuff you don't need. Note the locking for the thread count etc. I guess you would add a collection to store references to the threads that register themselves with the singleton.

To get a reference to the instance of the singleton, use the following code:

            CrLicenseLock oCrLicenseLock = CrLicenseLock.GetInstance();

the class is as follows:

        private sealed class CrLicenseLock
        {
            private int mnLicenseCount = 0;
            private const int LICENSE_COUNT_MAX = 3;
            private const int TIMEOUT = 1000;
            private AutoResetEvent moARE = null;

            #region Constructor etc
            static readonly CrLicenseLock instance=new CrLicenseLock();
            /// <summary>
            /// the method could easily be converted to a property with only an accessor,
            /// with no impact on thread-safety or performance.
            /// </summary>
            /// <returns></returns>
            public static CrLicenseLock GetInstance()
            {
                return instance;
            }
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static CrLicenseLock()
            {
            }
            public CrLicenseLock()
            {
                moARE = new AutoResetEvent(false);
            }
            #endregion

            #region External Methods
            #region LicenseGet
            /// <summary>
            /// should only be called from a try block, with a finally block containing the LicenseReturn
            /// would be improved by implementing a queuing system,
            /// would avoid numerous threads all hitting license count simultaneously
            /// however, only scaling issue, and if it were an issue
            /// the number of cr licenses would be woefully inadequate.
            /// </summary>
            /// <returns></returns>
            //
            public bool LicenseGet()
            {
                bool bReturn = false;
                bool bFirstTime = true;

                DateTime dtStart = DateTime.Now;

                do
                {
                    if(bFirstTime)
                        bFirstTime = false;
                    else
                    {
                        //all will clamour when signalled, but not big problem
                        moARE.WaitOne(TIMEOUT - DateTime.Now.Subtract(dtStart).Milliseconds, false);
                    }

                    lock(this)
                    {
                        if(mnLicenseCount < LICENSE_COUNT_MAX)
                        {
                            mnLicenseCount++;
                            bReturn = true;
                        }
                    }
                }while(bReturn == false && DateTime.Now.Subtract(dtStart).Milliseconds < TIMEOUT);

                return bReturn;
            }
            #endregion
            #region LicenseReturn
            public void LicenseReturn()
            {
                lock(this)
                {
                    mnLicenseCount--;
                }
                moARE.Set();
            }
            #endregion
            #endregion
        }


Cheers!
0
 
LVL 3

Author Comment

by:mandalorian4
Comment Utility
boblah,

Thank you for the prompt response.  I will try to incorporate your solution shortly.  I noticed you used.

I am afraid I still do not understand how to identify a thread when multiple threads are created.  I see in my locals window a thread ID, but I do not see how to set or get the property.



Thank you.
0
 
LVL 10

Expert Comment

by:ptmcomp
Comment Utility
AppDomain.GetCurrentThreadId() returns the unique id of the current thread.
You can assign a name to a thread.
To increment / decrement values threadsafe you can use the Interlocked.Decrement / Interlocked.Increment methods. (Evaluate the return value not the value in the variable)
0
 
LVL 10

Expert Comment

by:ptmcomp
Comment Utility
BTW: You can not set the thread id. It's given by the system.
0
 
LVL 6

Expert Comment

by:boblah
Comment Utility
mandalorian4,

More details on creating a singleton

    /// <summary>
    /// Summary description for SingletonTest.
    /// This object works as a singleton
    /// for details of why this is the best way to do a proper, thread safe, lazy loaded singleton
    /// (one other way for full lazy loading, but slightly higher performance cost)
    /// see: http://www.yoda.arachsys.com/csharp/singleton.html
    /// sealed declaration is not strictly necessary, but might help optimisation
    /// </summary>
    public sealed class SingletonTest
    {
        public string CreateTime = "";

        #region Constructor etc
        private static readonly SingletonTest instance = new SingletonTest();
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static SingletonTest()
        {
        }
        public SingletonTest()
        {
            CreateTime = System.DateTime.Now.ToString();
        }
        /// <summary>
        /// the method could easily be converted to a property with only an accessor,
        /// with no impact on thread-safety or performance.
        /// </summary>
        /// <returns></returns>
        public static SingletonTest GetInstance()
        {
            return instance;
        }
        #endregion


    }
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now