To understand that let us take a look at how applications typically run. Typically when you are writing a program it executes one method at a time. The CPU executes a method then once it finishes moves to the next one. This is known as synchronous programming.
I’m a big fan of understanding the taxonomy and etymology of words. I feel like it gives a lot of initial insight. So let’s look at the root word:
> syn·chro·nize: cause to occur or operate at the same time or rate.
So the idea with synchronous programming is that things all happen at the same rate. One thing starts, and then the next thing starts afterward, in order, at the same rate.
Asynchronous programming means being able to do things out of order, I.E. not synchronized.
The basic building block of asynchronous programming is the Thread. A thread has 2 meanings. It is often referred to with CPU’s as for how many individual sets of synchronous actions the processor can to at the same time (in parallel.) It is also a logical unit that the operating system uses to manage tasks that it is sending to the CPU. So the processor its self may only have a few threads it can run in parallel, but the OS may have thousands of threads open at any given time depending on how many applications are running and what each of those applications is doing.
It’s like a bank. There are more customers than clerks, so everyone gets in a line and as a clerk becomes available they help the customer. Likewise, individual threads are either making deposits or making withdrawals. When they are “depositing” they have an action they need to preform then leave and let the bank do its thing. When they make a withdrawal the customer waits for a returned sum of money.
static void Main(string[] args) { Thread bankThread = new Thread(() => { Thread.Sleep(500); Console.WriteLine("Bank: Money has is now available in the account."); }); Console.WriteLine("Customer: I would like to deposit"); Console.WriteLine("Clerk: No problem"); bankThread.Start(); Console.WriteLine("Customer: Thank you"); Console.ReadLine(); }
This will generate the following output:
Customer: I would like to deposit
Clerk: No problem
Customer: Thank you
Bank: Money is now available in the account.
Making a withdrawal is a little different because we have to have some way of giving the customer back something from the thread. We do this with a callback.
static void Main(string[] args) { Thread withdrawThread = new Thread(x => { Thread.Sleep(500); decimal money = 20; Console.WriteLine("Clerk: Here is {0:C2}", money); var callback = (x as Action); callback(money); }); Action customerCallback = money => { Console.WriteLine("Customer: Thank you for the {0:C2}", money); }; Console.WriteLine("Customer: Hi, I'd like twenty dollars"); Console.WriteLine("Clerk: No problem, let me get that for you"); withdrawThread.Start(customerCallback); Console.WriteLine("Customer: twiddles thumbs"); Console.ReadLine(); }
This will generate the following output:
Customer: Hi, I’d like twenty dollars
Clerk: No problem, let me get that for you
Customer: twiddles thumbs
Clerk: Here is $20.00
Customer: Thank you for the $20.00
So I hope this helps you find the thought of asynchronous programming a lot less scary. I’ll be writing more articles on the subject and how we leverage the Task Parallel Library, how all of this relates to async and await, and how we handle and log exceptions.
If you would like to be a guest contributor to the Stackify blog please reach out to [email protected]