About
In this code snippet, we will take a look at threads in C#.
Usually, the code we write executes procedurally(line by line). So if we have a time-consuming task like writing to a file(which can be very slow compared to the speed at which things happen in the CPU) our program will have to wait for that operation to be over before continuing with its execution.
You can solve this problem by making a new child thread that will branch off the main one and run in parallel. This way the main thread can continue to run and the time-consuming operation will be executing in the child thread and not holding up the main one. I should also note that it makes sense to use a new thread only for CPU bound operations and not for I/O bound ones. See this post I made for more information on the topic.
By default, threads are started as foreground threads. If you want to make a background thread you must set the IsBackground property to true before starting it. The difference between these two is that the foreground threads will keep running until they are done even if the parent thread was terminated. Meanwhile, a background thread will terminate when its parent thread is terminated even if it still has work to do.
Note:
Most of the time the threads don’t actually run in parallel. Each one gets to run for some time after that CPU time is given to another one. It all just happens so fast it appears as if things are running in parallel.
If you open up your task manager and look at the number of threads running you will see that you are probably running thousands of threads at once and you probably have something like 4-16 physical cores(and 8-32 virtual cores if your CPU supports hyperthreading). If we hand as many CPU cores as we have threads than all our threads could truly run in parallel. But it this case only 4-32 threads will actually run-in parallel.
Let’s have a look at the code below to see how to use threads.
Layout:
Code:
using System.Threading; using System.Windows; using System.Windows.Media; namespace Threads { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void changeButton_Click(object sender, RoutedEventArgs e) { //Change rectangle colors. if (rectangle.Fill == Brushes.Red) { rectangle.Fill = Brushes.Blue; } else { rectangle.Fill = Brushes.Red; } } private void workButton_Click(object sender, RoutedEventArgs e) { if ((bool)useThreadsCheckBox.IsChecked) { //Now doWork() runs as a separate thread. The app is now responsive even when doWork() runs. Thread workThread = new Thread(doWork); //Run thread. workThread.Start(); /*1.*/ //Thread workThread = new Thread(doWork); //This can be written in the following ways as well(using a delegate): /*1.1*/ //Thread workThread = new Thread(new ThreadStart(doWork)); /*1.2*/ //Thread workThread = new Thread(()=> doWork()); /*1.3*/ //Thread workThread = new Thread(delegate() { doWork(); }); } else { //The app will be unresponsive untill doWork() is finsihed. doWork(); } } //This method does time consuming work. static void doWork() { Thread.Sleep(4000); } } }