Skip to content

Instantly share code, notes, and snippets.

@heiswayi
Last active April 3, 2024 14:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heiswayi/296c4de4db6e34798be28f90aa47cf47 to your computer and use it in GitHub Desktop.
Save heiswayi/296c4de4db6e34798be28f90aa47cf47 to your computer and use it in GitHub Desktop.
C# Multithreadings (Thread, Threadpool, Task & BackgroundWorker) vs single threading experiment. https://nrird.com/blog/multithreading-programming
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace MultithreadingVsSingleThreading
{
internal class Program
{
#region Fields
private static int selectedMode;
// The number of threads to be spawned.
private const int threadCount = 1000;
// The total number of spins the actual work is carried out repeatedly.
private const int totalCount = 100000;
#endregion Fields
#region Methods
private static void Main(string[] args)
{
Console.Title = "Multithreading vs Single Threading Example";
start:
Console.WriteLine("Select which mode to run:-");
Console.WriteLine(" (1) Multithreading");
Console.WriteLine(" (2) Single Threading");
Console.WriteLine(" (3) Threadpool");
Console.WriteLine(" (4) Task");
Console.WriteLine(" (5) BackgroundWorker");
var input = Console.ReadLine();
if (input.Length == 0)
{
Console.Clear();
goto start;
}
else if (Convert.ToInt32(input) == 0 || Convert.ToInt32(input) >= 6)
{
Console.Clear();
goto start;
}
else
{
selectedMode = Convert.ToInt32(input);
}
Thread.CurrentThread.Priority = ThreadPriority.Highest;
Stopwatch watch = new Stopwatch();
Console.Clear();
watch.Start();
try
{
HandleMode(selectedMode);
watch.Stop();
Console.WriteLine("Work complete!");
Console.WriteLine("Time elapsed: {0}", watch.Elapsed);
Console.WriteLine(Environment.NewLine);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Press Enter key to test again or Esc to quit");
Console.ResetColor();
var key = Console.ReadKey();
if (key.Key == ConsoleKey.Enter)
{
Console.Clear();
goto start;
}
if (key.Key == ConsoleKey.Escape) Environment.Exit(0);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
/// <summary>
/// Performs the task based on user defined option.
/// </summary>
/// <param name="mode"></param>
private static void HandleMode(int mode)
{
switch (mode)
{
case 1:
Console.WriteLine("Using Thread() | No. of threads = {0}", threadCount);
Console.WriteLine("Initialize work...");
RunThreadMode();
break;
case 2:
Console.WriteLine("Using this Main() thread, directly call ComplexWork({0})", totalCount);
Console.WriteLine("Initialize work...");
ComplexWork(totalCount);
break;
case 3:
Console.WriteLine("Using ThreadPool.QueueUserWorkItem() | No. of threads = {0}", threadCount);
Console.WriteLine("Initialize work...");
RunInThreadPool();
break;
case 4:
Console.WriteLine("Using Task() | No. of threads = {0}", threadCount);
Console.WriteLine("Initialize work...");
RunTaskMode();
break;
case 5:
Console.WriteLine("Using BackgroundWorker() | No. of threads = {0}", threadCount);
Console.WriteLine("Initialize work...");
RunInBackgroundWorker();
break;
default:
break;
}
}
#region Work Task
/// <summary>
/// Performs CPU intensive task.
/// </summary>
/// <param name="n"></param>
private static void ComplexWork(int n)
{
for (int j = 0; j < n; j++)
{
for (int i = 1; i < 100; i++)
{
Fac(i);
}
}
}
/// <summary>
/// Calculates the factorial of a number.
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
private static double Fac(double n)
{
if (n > 1)
{
return n * Fac(n - 1);
}
else
{
return 1;
}
}
#endregion Work Task
/// <summary>
/// Spawns new threads based on the thread count and starts the activity.
/// </summary>
private static void RunThreadMode()
{
Thread[] t = new Thread[threadCount];
for (int i = 0; i < threadCount; i++)
{
t[i] = new Thread(() =>
{
ComplexWork(totalCount / threadCount);
});
t[i].Priority = ThreadPriority.Highest;
t[i].Start();
}
// Waits for all the threads to finish.
foreach (var ct in t)
{
ct.Join();
}
}
/// <summary>
/// Executes the task in a thread pooling context.
/// </summary>
private static void RunInThreadPool()
{
using (CountdownEvent signaler = new CountdownEvent(threadCount))
{
for (int i = 0; i < threadCount; i++)
{
ThreadPool.QueueUserWorkItem((x) =>
{
ComplexWork(totalCount / threadCount);
signaler.Signal();
});
}
signaler.Wait();
}
}
/// <summary>
/// Creates a new task based on the TPL library.
/// </summary>
private static void RunTaskMode()
{
Task[] taskList = new Task[threadCount];
for (int i = 0; i < threadCount; i++)
{
taskList[i] = new Task(new Action(() =>
{
ComplexWork(totalCount / threadCount);
}));
taskList[i].Start();
}
Task.WaitAll(taskList);
}
/// <summary>
/// Starts BackgroundWorker to perform the same action.
/// </summary>
private static void RunInBackgroundWorker()
{
BackgroundWorker[] backgroundWorkerList = new BackgroundWorker[threadCount];
using (CountdownEvent signaler = new CountdownEvent(threadCount))
{
for (int i = 0; i < threadCount; i++)
{
backgroundWorkerList[i] = new BackgroundWorker();
backgroundWorkerList[i].DoWork += delegate (object sender, DoWorkEventArgs e)
{
ComplexWork(totalCount / threadCount);
signaler.Signal();
};
backgroundWorkerList[i].RunWorkerAsync();
}
signaler.Wait();
}
}
#endregion Methods
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment