I've got the following multithreaded code for calculating Euler's number. I'm new in multithreaded programming and maybe I'm missing something. For some reason countdown.Wait() is not waiting for all the threads and totalSum is different almost every time. It looks like it skips some of the intermediate sums.
public static class Program
{
private static int elementsCount = 500;
private static int threadsCount = 20;
private static string outputFileName = "defaultFileName.txt";
private static bool isInQuietMode = false;
private static BigRational totalSum = new BigRational(0.0m);
private static CountdownEvent countDown = new CountdownEvent(threadsCount);
private static Object locker = new Object();
private static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int threadIndex = 0; threadIndex < threadsCount; threadIndex++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(CalculateEulerNumber), threadIndex);
}
countDown.Wait();
File.WriteAllText(outputFileName, "Euler's number: " + totalSum);
stopwatch.Stop();
Console.WriteLine("Result: ");
Console.WriteLine("Total time elapsed - " + stopwatch.Elapsed);
if (!isInQuietMode)
{
Console.WriteLine("Euler's number - " + totalSum);
}
}
private static void CalculateEulerNumber(object threadIndexObject)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
int threadIndex = Convert.ToInt32(threadIndexObject);
BigRational sum = new BigRational(0.0m);
for (int k = threadIndex; k < elementsCount; k += threadsCount)
{
BigRational numerator = BigRational.Pow((3 * k), 2) + 1;
BigRational denominator = Factorial(3 * k);
sum += BigRational.Divide(numerator, denominator);
}
totalSum = BigRational.Add(totalSum, sum);
stopwatch.Stop();
lock (locker)
{
int threadNumber = threadIndex + 1;
Console.WriteLine("Тhread " + threadNumber + ": ");
Console.WriteLine("Time elapsed - " + stopwatch.Elapsed);
if (!isInQuietMode)
{
Console.WriteLine("Intermediate sum - " + sum.ToDecimalString(40));
}
Console.WriteLine();
}
countDown.Signal();
}
private static BigRational Factorial(int n)
{
BigRational factorial = 1;
for (int i = 1; i <= n; i++)
{
factorial *= i;
}
return factorial;
}
}
@usr made a good point: you better use
ConcurrentStack<T>
orConcurrentQueue<T>
as detailed in http://msdn.microsoft.com/en-us/library/system.collections.concurrent%28v=vs.110%29.aspx. Also, it's better to implement your algorithm using Task.Factory as explained by Alexandra Rusina in http://blogs.msdn.com/b/csharpfaq/archive/2010/06/01/parallel-programming-in-net-framework-4-getting-started.aspx. As per the mentioned resources, your solution may look like something following (giving you general idea)Hope this will help. Rgds,