Wednesday, October 17, 2007

Using a Thread Pool in C# for Multiple Currency Conversion

.NET Classes used :
System.Collections.Generic.List
System.Threading.ManualResetEvent
System.Threading.Thread
System.Threading.ThreadPool
System.Threading.WaitHandle
System.Threading.ThreadStart

Introduction

A thread pool is a collection of threads that can be used to perform a number of tasks in the background. This relieves the primary thread free to perform other tasks asynchronously. Thread pools are often employed in server kind of applications. Each incoming request is assigned to a thread from the thread pool, so the request can be processed asynchronously, without locking up the primary thread or delaying the processing of subsequent requests in the queue. Once a thread in the pool completes its task, it is returned to a queue of waiting threads, where it can be reused. This reuse enables applications to avoid the overhead of creating a new thread for each task. Thread pools typically have a maximum number of threads. If all the threads are busy, additional tasks are placed in queue until they can be serviced as threads become available. It is easier to use the thread pool provided by the .NET Framework through the ThreadPool class as against creating a custom thread pool of our own.


Real World Example: Multi currency converter

Here is an example of multi currency conversion is simulated; which does processing of currency conversion. An exchange unit is modeled by a class called ExchangeUnit which carries the information of input & output currency and amount to be converted. Multiple objects of ExchangeUnit are created with different currency information and are fed into a ThreadPool for doing the multiple conversions. The ExchangeUnit class provides a method called ThreadPoolCallback that performs the conversion. An object representing each exchange required is created, and the ThreadPoolCallback method is passed to QueueUserWorkItem, which assigns an available thread in the pool to execute the method.
There is another class called MulticurrencyExchanger which maintains an internal list of latest conversion rates among the currencies. This list is periodically updated by a different thread which arrives at the percentage change in exchange rates based on a random number principle. In real world application latest exchange rates would be fed typically fed by a web service.
Here is the code for different classes:

using System;using System.Collections;using System.Collections.Generic;using System.Threading;using ClassLibrary;class Program{ static void Main(string[] args) { //Invoke the MulticurrencyExchanger Init() method on a separate thread MulticurrencyExchanger exchanger = new MulticurrencyExchanger(); Thread thread = new Thread(new ThreadStart(exchanger.Init)); thread.Start(); ExchangeUnit[] exchanges = new ExchangeUnit[3]; // One event is used for each ExchangeUnit object ManualResetEvent[] signalEvents = new ManualResetEvent[3]; for (int i = 0; i < 3; i++) { signalEvents[i] = new ManualResetEvent(false); } exchanges[0] = new ExchangeUnit(100.00, "USD", "RS", signalEvents[0]); exchanges[1] = new ExchangeUnit(100.00, "EURO", "RS", signalEvents[1]); exchanges[2] = new ExchangeUnit(100.00, "GBP", "RS", signalEvents[2]); // Calculate exchanges for 10 times so that fluctuating exchange rates reflect for (int j = 0; j < 10; j++) { // Launch threads for an ExchangeUnit using ThreadPool for (int i = 0; i < 3; i++) { ThreadPool.QueueUserWorkItem(exchanges[i].ThreadPoolCallback, exchanges[i]); } // Wait for all threads in pool WaitHandle.WaitAll(signalEvents); // Display the results for (int i = 0; i < 3; i++) { Console.WriteLine("{0} {1}={2} {3}", exchanges[i].CurrencyIn, exchanges[i].Amount, exchanges[i].CurrencyOut, exchanges[i].ExAmount); } // Sleep for 1 sec before going to next iteration Thread.Sleep(1000); } // Stop the thread for the MulticurrencyExchanger object thread.Abort(); Console.ReadLine(); }}