How To Write Bulletproof Multi-Threaded C# Code

This course teaches you how to write robust multi-threaded C# code. A skill every professional .NET developer must know
4.7 (80 ratings) Instead of using a simple lifetime average, Udemy calculates a
course's star rating by considering a number of different factors
such as the number of ratings, the age of ratings, and the
likelihood of fraudulent ratings.
1,404 students enrolled
$90
Take This Course
  • Lectures 29
  • Contents Video: 3 hours
  • Skill Level All Levels
  • Languages English
  • Includes Lifetime access
    30 day money back guarantee!
    Available on iOS and Android
    Certificate of Completion
Wishlisted Wishlist

How taking a course works

Discover

Find online courses made by experts from around the world.

Learn

Take your courses with you and learn anywhere, anytime.

Master

Learn and practice real-world skills and achieve your goals.

About This Course

Published 5/2015 English

Course Description

Updated on August 7, 2015. Added a new lecture on Thread Rendezvous.

BEST COURSE CHOICE for beginners and intermediate C# developers who want to learn how to write unbreakable multi-threaded code, and take their programming skills to the next level.

Do you know how to write robust multi-threaded C# code that does not crash?

Yeah, I thought I did too. In 2005 I built an RFID-enabled supermarket shelf and wrote some multi-threaded C# code to ping the antennas and automatically detect groceries fitted with an RFID tag.

The result? The program was very unstable and crashed many times. My client did eventually manage to perform a successful demo, but it required a lot of reboots.

Why was my code so unstable? Because I had forgotten to put critical sections around some of the variables that were shared between threads.

Writing multi-threaded code is hard. The sobering truth is that, unless you know exactly what you're doing, your code is pretty much guaranteed to crash in production.

Don't let this happen to you!

It doesn't have to be like this. If you have a good understanding of multi-threaded programming and follow a few simple industry best practices, you can write robust code that can take a beating.

I wrote a multi-threaded conversion utility a few months ago, that successfully migrated 100,000 documents from SharePoint 2010 to SharePoint 2013. The program worked flawlessly the first time, because I implemented all of the best practices for writing asynchronous C# code.

Sound good?

In this course I am going to share these practices with you.

In a series of short lectures I will cover many multi-threading topics. I will show you all of the problems you can expect in asynchronous code, like race conditions, deadlocks, livelocks and synchronisation issues. I'll show you quick and easy strategies to resolve these problems.

By the end of this course you will be able to write robust multi-threaded C# code that can take a beating.

Why should you take this course?

You should take this course if you are a beginner or intermediate C# developer and want to take your skills to the next level. Asynchronous programming might sound complicated, but all of my lectures are very easy to follow, and I explain all topics with clear code and many instructive diagrams. You'll have no trouble following along.

Or maybe you're working on a critical section of code in a multi-threaded C# project, and need to make sure your code is rock-solid in production? The tips and tricks in this course will help you immensely.

Or maybe you're preparing for a C# related job interview? This course will give you an excellent foundation to answer any threading-related questions they might throw at you.

30 day money-back guarantee

This course comes with an unconditional, Udemy backed, 30-day money-back guarantee. If you are dissatisfied with the course for any reason, simply request a refund and get your full purchase amount back, no questions asked.

Act now

This course today contains over 3 hours of video content and I am adding new material every month. Enrol now to benefit from the current price and get free lifelong access to all future materials.

Enrol now!

What are the requirements?

  • You should have a Windows, Mac or Linux laptop with Microsoft Visual Studio, Xamarin Studio or Monodevelop installed
  • You should be familiar with the C# language
  • That's all!

What am I going to get from this course?

  • Learn how to write bulletproof multi-threaded C# code from a certified Microsoft trainer from your own desk.
  • Many hours of video content teaching you about threads, race conditions, deadlocks, and much more!
  • Suitable for beginner and intermediate programmers and ideal for users who learn faster when shown.
  • Learn how to use the Thread class
  • What's a race condition, and how do you resolve it?
  • Deadlocks and livelocks - how to deal with them
  • Learn all about the Dining Philosopher problem

What is the target audience?

  • This course is for beginner and intermediate C# programmers who want to learn how to write bulletproof multi-threaded C# code
  • Ideal for students who are about to take a job interview, and need to prepare for multithreading-related questions
  • Are you writing a section of multi-threaded code in a large C# project, and need to be sure it will not crash in production? Then this course is for you!

What you get with this course?

Not for you? No problem.
30 day money back guarantee.

Forever yours.
Lifetime access.

Learn on the go.
Desktop, iOS and Android.

Get rewarded.
Certificate of completion.

Curriculum

Section 1: Introduction
04:07

In this lecture I explain how this course is organised and I describe each of the upcoming sections in detail.

03:50

In this lecture I will tell a bit more about myself, my career, and my motivation to become an online trainer.

04:25

In this lecture we're going to look at the theory behind asynchronous programming. What exactly is multithreaded code, and how does it work?

03:19

Many lectures in this course contain source code examples. Feel free to download the code and follow along. And here's the good news: it doesn't matter if you have a Window, Mac or Linux computer. The code will run on all three operating systems.

In this lecture I demonstrate how my solutions and projects run on all operating systems. I will show you how to build and run the source code on a Mac, on Linux and in Visual Studio running on Windows 8.

At the end of this lecture you will have learned that .NET code is portable and can run on at least five different operating systems.

Section 2: Working With Threads
00:50

Welcome to the Thread Class section. I will give a quick introduction on how the section is organized before we get started.

08:55

In this lecture I will teach you how to start new threads using the System.Thread class: the workhorse of multi-threaded programming in C#.

I will also show you how you can give a descriptive name to a thread, to aid in debugging.

Finally, you will learn that there are two classes of threads: foreground- and background threads. I will show you the difference in behaviour between these two classes of threads.

03:50

In this lecture I am going to show you the most common multi-threading programming problem: a race condition.

A race condition happens when 2 or more threads are trying to access and modify the same variable. I will demonstrate a race condition with a very simple program, with 2 threads accessing a shared integer class member.

In the next section I will show you a comprehensive solution for dealing with race conditions. For now I will leave you with a tip on how to minimize the impact of race conditions in your code.

07:22

In this lecture you will learn how to safely pass in initialization data to a thread. You will learn about the ParameterizedThreadStart delegate, and how to use a lambda expression to initialize a thread.

Captured variables in lambda expressions are shared between the new thread and the main program thread, and so this opens us up to a possible race condition.

I will show you a short program that uses a lambda expression and introduces a race condition. Then I'll show you a cool trick, where I only change 2 lines of code, to make the race condition disappear.


05:43

In this lecture I am going to show you another common multi-threading programming problem: checking if a thread has finished.

I will show you a short multi-threaded program with a block of code that I want to be executed once. Two threads check each other's state to ensure that the code executes only a single time. I'll show you a working solution that actually has a big hidden problem. You will learn that the program only works by pure coincidence.

I will conclude the lecture with some advice on the best way to check if a thread has finished.

05:05

In this lecture you will learn how to suspend the current thread until another thread has completed, using the Join method. We will revisit the multi-threaded program with the race condition from the previous lecture. I will show you how a single strategically placed Join statement resolves the race condition.

In the second part of this lecture I will show you how you can suspend the current thread for a given time interval by using the Sleep method.

We'll conclude with a summary of what we have learned.

07:43

The previous lecture introduced the Join and Sleep methods which suspend the current thread until either another thread ends, or when a given timeout expires.

In this lecture you will learn how to interrupt and abort suspended threads. We will look in detail at what precisely happens when you interrupt or abort a suspended or a non-suspended thread.

Even though the Interrupt and Abort methods look really useful, using them in practice is somewhat risky. We'll look at how an unexpected interrupt or abort can introduce resource leaks, and I will provide two scenarios in which you can safely abort a thread without having to worry about leaks.

03:45

Congratulations on finishing this section. This is a recap of what we have learned.

10 questions

Test your knowledge of the thread class with this short quiz.

Section 3: Introducing Thread Locking
01:04

Welcome to the Thread Locking section. I will give a quick introduction on how the section is organized before we get started.

08:27

In the previous section I showed you several multi-threaded programs that were prone to a specific problem called a 'race condition'.

In this lecture I revisit the race condition and I'll demonstrate how a special technique called 'thread locking' resolves the problem. I will show you several short examples of code prone to race conditions, and then I'll add thread locking to the code to fix the problem.

At the end of this lecture you will know exactly what thread locking is, how it resolves a race condition, and when you should implement it yourself.

10:59

In this lecture we are going to take a closer look at the lock statement in C#. You will learn that "lock" is in fact syntactic sugar for a pair of Monitor.Enter and Monitor.Exit calls. I will demonstrate several example programs using either the compact "lock" syntax, or the more verbose code that uses the Monitor class.

You will learn all the essentials of thread locking, including what code to lock, which synchronisation object to use, and what the advantages are of calling the Monitor class directly.

By the end of the lecture you will be proficient in thread locking, and you will be able to set up critical sections in your code with ease.

07:28

This lecture explains how to deal with deadlocks. A deadlock is a problem that occurs when two or more threads are waiting indefinitely for each other, trying to access and lock two or more resources.

I will explain deadlocks in detail using the famous thought experiment created by Edsger Dijkstra in 1965: the "Dining Philosopher" problem. I will show you what a deadlock looks like when represented in the context of the dining philosophers.

We will then examine two quick-fix strategies for resolving deadlocks: introducing randomness, or use an arbiter.

After completing this lecture you will have a thorough understanding of what a deadlock is, and you will know two strategies for resolving deadlocks in your code. You will also be aware of the Chandy / Misra algorithm, which is the reference solution for the Dining Philosopher problem.

08:50

In this lecture we revisit the Dining Philosopher problem. I have written a simulation program that sets up all 5 philosophers and chopsticks, and implements the random sleep mitigation strategy that we discussed earlier. You will see that my implementation has terrible performance, with all 5 philosophers fighting for the chopsticks more than 90% of the time.

Can you do better than me?

Your assignment is to take my code as a starting point and write your own improved deadlock resolving strategy. The objective is to have all philosophers eat for as long as possible. The highest score you can achieve is slightly over 20 seconds.

Good luck!

10:46

In this lecture we are going to take a closer look at a specific scenario: locking and incrementing a single variable. You already learned that you can make an increment operation thread-safe by using a lock statement. But unfortunately a lock has a performance overhead which will slow down your code.

Fortunately there is an alternative. For simple scenarios like incrementing, decrementing, reading or writing a single variable, you can also use the Interlocked class. The Interlocked class exposes low-level thread-safe CPU operations which perform much better than a generic lock statement.

In this lecture we are going to take a closer look at the performance difference between thread-unsafe and thread-safe code, and between the generic lock statement and the Interlocked class.

By the end of this lecture you will have learned if using the Interlocked class is worth the effort.

02:39

Congratulations on finishing this section. This is a recap of what we have learned.

5 questions

Test your knowledge of thread locking with this short quiz.

Section 4: How To Synchronise Threads
01:19

Welcome to the Thread Synchronisation section. I will give a quick introduction on how the section is organised before we get started.

15:18

In this lecture I am going to take a look at thread synchronisation. The need for thread synchronisation arises when two or more threads need to exchange data in a controlled manner. I will show you a simple example program that attempts to exchange data between threads without any synchronisation, and you will see how the data transfer completely fails.

Next we will cover the workhorse of thread synchronisation: the AutoResetEvent. I will show you how you can line up two threads with a single AutoResetEvent variable, to ensure that you'll never lose any data. Then I'll show you how the single remaining race condition can be resolved by adding a second AutoResetEvent.

By the end of the lecture you will have a deep understanding of thread synchronisation: what it is, when you need it, and how you can implement it yourself.

10:42

In this lecture I am going to build a producer/consumer queue which is a very popular multi-threaded coding pattern. The queue features one or more 'producers' which add tasks to a shared queue, and a pool of 'consumers' that retrieve tasks from the queue and execute them in the background.

I will show you how you can build a producer/consumer queue in .NET with only a simple thread-safe queue of delegates, and one AutoResetEvent to notify consumers that a new task is available.

By the end of the lecture you will be able to build your own producer/consumer queue, and you will also have learned a surprising fact about the console.

11:59

So far we've only used AutoResetEvents to synchronise two or more threads. In this lecture I'm going to take a closer look at the ManualResetEvent, a wait handle similar to the AutoResetEvent but with a slightly different behaviour.

I will start with the producer/consumer queue from the previous lecture, and add new pause and resume functionality. I will show you what happens when you try and build that functionality with an AutoResetEvent (hint: it doesn't work). Then I'll show you how the ManualResetEvent behaves, and I will change the code to make the queue work as intended.

By the end of the lecture you will have a clear understanding of the differences between an AutoResetEvent and a ManualResetEvent, and you will have learned how to use the latter in the producer/consumer queue to make all consumers pause or resume their work.

12:57

You have seen how the AutoResetEvent can be used to signal an event from one thread to another, and how the ManualResetEvent can be used to signal from one thread to an entire group of threads.

In this lecture I am going to cover a third scenario: how to signal from a group of threads to a single thread. I will show you how the CountdownEvent, a new type of wait handle, can be used to implement this scenario. I will revisit the producer / consumer queue, and use a CountdownEvent to add a new feature that lets me quit all consumers simultaneously.

By the end of the lecture you will have a clear understanding of the differences between the AutoResetEvent, the ManualResetEvent and the CountdownEvent.

14:38

In this lecture I will describe 'Thread Rendezvous' which is the process of aligning two or more threads in time, to execute the same part of code simultaneously.

There are several ways to implement thread rendezvous, and you have already seen one method that uses two complimentary AutoResetEvents to synchronise two threads. I will show you two other techniques that solve several problems with the AutoResetEvents solution.

By the end of the lecture you will have learned what the Barrier class is for, and how it solves several problems that pop up when you try to implement thread rendezvous with AutoResetEvents or a CountdownEvent.

03:01

Congratulations on finishing this section. This is a recap of what we have learned.

Thread Synchronisation
10 questions
Section 5: Final Words
01:54

In this lecture I would like to thank you for finishing the course and offer some final words.

Section 6: Bonus section
02:34

In this bonus lecture I would like to offer you an exclusive discount on another of my courses that teaches you how to radically speed up your C# code.

02:37

In this bonus lecture I would like to offer you an exclusive discount on another of my courses that teaches you all about C# anti-patterns and bad coding practices.

Students Who Viewed This Course Also Viewed

  • Loading
  • Loading
  • Loading

Instructor Biography

Mark Farragher, Microsoft Trainer

Hi I'm Mark, and I am very pleased to meet you!

My IT career spans 2 decades and I've worn many different hats over the years. I am a serial entrepreneur and have launched two startups in The Netherlands. I've also been a CTO three times.

I started working with C# and the .NET framework 15 years ago. Today I live in Barcelona and spend my time creating online courses to share my knowledge of professional C# programming with a wide audience.

Ready to start learning?
Take This Course