Library tutorials & articles

.NET Threading Part I

Thread Pools

I was very impressed when I found out that the .NET framework library included the "System.Threading.ThreadPool" class. I was also impressed by how easy it was to use. You need not create the pool of threads, nor do you have to specify how many consuming threads you require in the pool. The ThreadPool class handles the creation of new threads and the distribution of the wares to consume amongst those threads.

You can kick off a consuming thread pool by simply invoking the ThreadPool. QueueUserWorkItem static method.

ThreadPool.QueueUserWorkItem( new WaitCallback( Consume), ware);

The parameters of the QueueUserWorkItem static method are the WaitCallback delegate that wraps the instance method used in consuming your ware and the ware that you are passing to the method. Your consuming instance method must return void and take one object parameter. The ware that is passed to the QueueUserWorkItem method will be passed into your consuming instance method as the one object parameter. (For the rest of this article I define a ware to be an item that is produced by the producing thread and consumed by a consuming thread in the consumer-producer design pattern. This is a very narrow definition of the word, but one that suits this article. )

public void Consume(Object obj)

Again, the simplicity of C# and the .NET framework shine through. In just a few lines of code, I've recreated a multithreaded consumer-producer application (see below).

using System;
using System.Threading;
using System.Diagnostics;

namespace ConsoleApplication2
{
    public class Ware
    {
        public int id;
        public Ware(int _id)
        {
            id = _id;
        }
    }

    class Class1
    {
        public int QueueLength;

        public Class1()
        {
            QueueLength = 0;
        }

        public void Produce(Ware ware)
        {
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(Consume), ware);
            QueueLength++;
        }

        public void Consume(Object obj)
        {
            Console.WriteLine("Thread {0} consumes {1}",
                Thread.CurrentThread.GetHashCode(), //{0}
                ((Ware) obj).id); //{1}
            Thread.Sleep(100);
            QueueLength--;
        }

        public static void Main(String[] args)
        {
            Class1 obj = new Class1();
            for (int i = 0; i < 1000; i++)
            {
                obj.Produce(new Ware(i));
            }
            Console.WriteLine("Thread {0}",
                Thread.CurrentThread.GetHashCode() ); //{0}
            while (obj.QueueLength != 0)
            {
                Thread.Sleep(1000);
            }
        }
    }
}

I added the line Thread.Sleep(100) in the Consume method to simulate the processing that a consumer would normally have performed on the ware. If I didn't include this Sleep'ing, then one consumer thread could have handled all 100 wares. The additional Sleep'ing forces the .NET framework to create additional threads and more accurately portrays the features of the ThreadPool class.

Comments

  1. 27 Feb 2004 at 22:06

    I was asked to do the following:
    write the method call to begin running the thread and begin processing
    (a) namespace = testProject
    (b) form to run = frmMain


    All the things that I have read on threading so far say that a thread point to a function of whatever comes after the "addressOf" in the argument.  Therefore, I don't understand what (a) and (b) are trying to refer to or specify.  If you happen to understand what that question is looking for, or know any good literature I can look at for the given topic, please let me know.  Thank you.
    email me

  2. 04 Nov 2003 at 15:04
    Quote:
    [1]Posted by James Crowley on 4 Nov 2003 02:52 PM[/1]
    Are you ensuring that the page doesn't finish loading before both threads have returned a result? Otherwise, you may find that ASP.NET is outputting the page to the client before the thread has actually called the callback!



    Yes...and if I may add, rather hesitantly at this juncture, I did think about that.
    What surprised me however was when I ran this in debugging mode, I as able to trace both callbacks
    and in one case the dataset returned had no data. I wonder if  there are any issues with returning non-simple types
    in the event driven call back. May be, using the delegate mechanism may work. I havn't done
    much callback based threading so far...
  3. 04 Nov 2003 at 14:52
    Are you ensuring that the page doesn't finish loading before both threads have returned a result? Otherwise, you may find that ASP.NET is outputting the page to the client before the thread has actually called the callback!
  4. 04 Nov 2003 at 13:20
    I have tried threading in my web page. I tried to fill two drop-downs by threading two methods in two different business layer objects from my web page. I used the event call back method  to return two datasets (one for each drop down) but got  inconsistent results..drop-downs were populated and sometimes not. Any ideas?
  5. 01 Jan 1999 at 00:00

    This thread is for discussions of .NET Threading Part I.

Leave a comment

Sign in or Join us (it's free).

Randy Charles Morin Randy's article are Copyright 1998-2003 Randy Charles Morin

Related podcasts

  • A Practical Look at Silverlight 2 Part 1

    Now that Silverlight 2 is at the Olympics and making a big splash, we wanted to explore this fascinating technology more. Microsoft Silverlight 2 is a cross-browser, cross-platform, and cross-device plug-in for delivering the next generation of .NET based media experiences and rich interactive ap...

Events coming up

  • Dec 9

    GL.net Group Meeting - December 2009

    Gloucester, United Kingdom

    The beginning of this year holiday season will belong to mocks. Ronnie and Stephen will take us for a tour around exciting world of unit testing.

We'd love to hear what you think! Submit ideas or give us feedback