C# Tutorials and offshore development in India
    Tutorials   Resources   Forum   Communities   Interview   Jobs   Projects   Offshore Development    
Silverlight Tutorials | Mentor | Code Converter | Articles | Code Factory | Computer Jokes | Members | Peer Appraisal | IT Companies | Bookmarks | Revenue Sharing |


Prizes & Awards
My Profile



Active Members
TodayLast 7 Days more...

New Feature: Community Sites: Create your own .NET community website and start earning from Google AdSense ! It's Free !




Using a Thread Pool in C# for Multiple Currency Conversion


Posted Date: 11 Sep 2007    Resource Type: Articles    Category: .NET Framework

Posted By: Prajnan Das       Member Level: Gold
Rating:     Points: 15



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.Generic;
using System.Text;
using System.Threading;

public class MulticurrencyExchanger
{
static List conversions;

static MulticurrencyExchanger()
{
// The conversion factors
conversions = new List();
conversions.Add(new ConversionInfo("USD", "RS", 40.00));
conversions.Add(new ConversionInfo("EURO", "RS", 47.00));
conversions.Add(new ConversionInfo("GBP", "RS", 73.00));
}

Random random = new Random();

public void Init()
{
Action action = UpdateConversionFactors;

// Loop infinitely
while (true)
{
int waitTime = random.Next(1000, 5000);
Thread.Sleep(waitTime);

lock (conversions)
{
// Apply conversion on the conversion list
conversions.ForEach(action);
}
}
}

// Wrapper method to apply updated conversion rates
void UpdateConversionFactors(ConversionInfo info)
{
int percentage = random.Next(-5, 5);
info.conversionFactor = info.conversionFactor * (1 + (double)percentage / 100);
}

// Service method to do a conversion on an ExchangeUnit
public static double Convert(ExchangeUnit exchange)
{
foreach (ConversionInfo info in conversions)
{
if (info.currencyIn.Equals(exchange.CurrencyIn) &&
info.currencyOut.Equals(exchange.CurrencyOut))
{
return exchange.Amount * info.conversionFactor;
}
}

return -1;
}
}

// Class to encapsulate a Conversion Information between currencies
internal class ConversionInfo
{
internal string currencyIn;
internal string currencyOut;
internal double conversionFactor;

internal ConversionInfo(string currencyIn, string currencyOut, double conversionFactor)
{
this.currencyIn = currencyIn;
this.currencyOut = currencyOut;
this.conversionFactor = conversionFactor;
}
}

// Class to encapsulate a Exchange request between two currencies
public class ExchangeUnit
{
double amount;
string currencyIn;
string currencyOut;

ManualResetEvent signal;
double exAmount;

public ExchangeUnit(double amount,
string currencyIn,
string currencyOut,
ManualResetEvent signal)
{
this.amount = amount;
this.currencyIn = currencyIn;
this.currencyOut = currencyOut;

this.signal = signal;
}

public double Amount
{
get { return amount; }
}

public string CurrencyIn
{
get { return currencyIn; }
}

public string CurrencyOut
{
get { return currencyOut; }
}

public double ExAmount
{
get { return exAmount; }
}

// Wrapper method for use with thread pool
public void ThreadPoolCallback(Object threadContext)
{
exAmount = MulticurrencyExchanger.Convert(threadContext as ExchangeUnit);
signal.Set();
}
}


Here is the test program:


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();
}
}


Here is a sample run output:

USD 100=RS 4000
EURO 100=RS 4700
GBP 100=RS 7300
USD 100=RS 4000
EURO 100=RS 4700
GBP 100=RS 7300
USD 100=RS 3800
EURO 100=RS 4841
GBP 100=RS 7227
USD 100=RS 3800
EURO 100=RS 4841
GBP 100=RS 7227
USD 100=RS 3800
EURO 100=RS 4841
GBP 100=RS 7227
USD 100=RS 3800
EURO 100=RS 4841
GBP 100=RS 7227
USD 100=RS 3914
EURO 100=RS 4744.18
GBP 100=RS 7154.73
USD 100=RS 3914
EURO 100=RS 4744.18
GBP 100=RS 7154.73
USD 100=RS 3953.14
EURO 100=RS 4696.7382
GBP 100=RS 7297.8246
USD 100=RS 3953.14
EURO 100=RS 4696.7382
GBP 100=RS 7297.8246

Note: I haven’t taken into account of rounding of the decimals to two decinmal places. Also the program will fail if there is an unlisted exchange request. I would leave these two drawbacks as exercise to the readers. Comments are welcome.

Summary


Principle of ThreadPool has been demonstrated through a real world simple example. ThreadPool aides in multiple tasking by relieving the programmer from creation and management of multiple threads.




Responses

Author: Help Aussie    13 Aug 2008Member Level: Bronze   Points : 1
how do you intend to use

static List conversions;

Do you have a separate class file for this?


Feedbacks      
Popular Tags   What are tags ?   Search Tags  
Using a Thread Pool in C# for Multiple Currency Conversion  .  Using a Thread Pool in C#  .  Using a Thread Pool for Multiple Currency Conversion  .  Using a Thread Pool  .  

Post Feedback


This is a strictly moderated forum. Only approved messages will appear in the site. Please use 'Spell Check' in Google toolbar before you submit.
You must Sign In to post a response.
Next Resource: String Concatenation in ASP.NET
Previous Resource: Working with Assembly
Return to Discussion Resource Index
Post New Resource
Category: .NET Framework


Post resources and earn money!
 
Related Resources



dotNet Slackers   BizTalk Adaptors    Web Design

efax

Contact Us    Privacy Policy    Terms Of Use