Part I. Overview
If you ever get a chance to hear Jeffery Richter speak, it is definitely worth it. I can sum up my leaning for today from devscovery in a couple of points.
1) Don't create new threads! Borrow them from the ThreadPool. (Lease threads.. don't buy em')
Jeffery pointed out that running more than one thread per processor available on the machine our classes are running will cause context switches. Context switches are expensive and will degrade the performance of any application, so if we want to create a new Thread, we need to have a really (really) good reason to do so and should be able to justify it like with a windows GUI when we are willing to sacrifice overall performance for a slicker user experience. For a middle tier dll, we should be able to keep it down to around one thread per processor on the machine (as long as no other threads are sleeping) to avoid context switches and if we use the baked-in ThreadPool, it will be optimized for us.
2) Architecting a system with asynchronous calls will automatically take advantage of the ThreadPool which will manage the threads for us.
If we use the asynchronous model to develop out applications, the runtime will take care of scaling our apps to how ever many processors are running on the box. So we can build software that takes advantage of quad core processors and in the (near) future, 16 core, 32 core, 64 core or even more processors. If we build apps with the asynchronous model in mind, they will scale to whatever box we install on.
Part 2. The Paradigm shift
Async programming is a big paradigm shift from procedural coding like in C or VB6 and also is a bit of a paradigm shift from straight OOP programming w/ C#. Basically we have to break our standard methods that handle IO (input/output) operations into separate "pieces" that handle input request and deliver the results separately. The farther we can do this through the call stack, the fewer blocks we'll have on running threads and thus we'll have fewer "stalls" in our cpu processes where the processor is waiting on something else (like a disk-read).
To give an example of splitting a method, I'll show you some basic code I'm working on to demonstrate to my colleagues what I took away from Jeffery's presentation.
Let's say we have an object that contains a long-running process. Normally this would be a I/O operation like a database query or a file read or write, but for demonstration purposes, we'll use a "fake" long-running process.
In the example below we have a slow running IntFetcher.SlowFetch() which is meant to simulate either a database call, a web service call, or some kind of disk I/O.
public static class IntFetcher
{
public static int SlowFetch()
{
// Simulate a long-running i/o process
Thread.Sleep(150); // DONT EVER DO THIS! FOR DEMO PURPOSES ONLY!
return 5;
}
}
If we have a method that calls IntFetcher.Fetch() the main thread in our app is basically locked up until the end of the method call. This can be a complete waste of time if the main thread is just waiting for a file I/O being handled by the hardware, a web service call waiting on a remote server, or a db call (imagine if we have thousands of users making this call from a web form… it could be a pretty ugly situation). Our main thread will get hung up on the slow method call waiting for a response when we could be putting it to work doing other things – like handling other requests.
public class BadPerf
{
public int FetchInt()
{
Console.WriteLine("Start Fetchin..");
int i =IntFetcher.Fetch();
Richard MulawaPosted Mar 29, 2018, 8:42 AM
Thanks I am new and trying to learn this multi-threading asynchronous programming pattern. I have to write code that has a gui user interface that connects to some boards via tcp and reads and displays information about the state of the boards on the gui interface and this gets me started. It is still a bit above my head but I will continue to follow these articles and hopefully it will start to make more sense. The problem I run into is I am starting at vs 2015 c# and there have been so many changes to the entire delegate callback and event programming model that as a new user you get totally wrapped around the axle because all the things from the base C# api has been wrapped with layers of under the hood changes that hide how the underlying api really works to the point where you are totally lost and the code samples look like total jibberish!!! This pretty much sums it up as a new user --- You have to know all the 2015 changes to understand 2018 examples but you have to know all the 2013 changes to understand the 2015 examples oh but wait you have to fully understand the 2010 changes to understand the 2013 examples....and you feel like your head is going to explode and you end up watching dog surfing videos on you tube because you have totally forgotten what you started out wanting to do!
Suraj PalapathwelaPosted Sep 25, 2012, 5:46 AM
good job... welldone!
MadApplesPosted Oct 24, 2009, 4:13 AM
Ok my bad, up till now ive been trying to create more threads...oops, my game is laggy, and was having bunches of trubles, i did google till i found this,, and just wanted to say THANK you for the nice, easy to follow tutorial that i will now aply to my game ive been developing. Be sure that ill folllow up on your other totorials ;) -MadApples
Anton KPosted Feb 29, 2008, 5:35 AM
Ye man! Good Job!
Anton KPosted Feb 29, 2008, 5:35 AM
Ye man! Good Job!
daveeditedPosted May 29, 2007, 11:31 AMEdited May 30, 2007, 3:25 PM
Edited for Clarification: I appreciate what you're saying; however, I've been looking into the asynch model for a while off and on, and I have lots of brick wallish experiences when I get to a remote host consuming data that's produced asynchronously on the server. I know that asp.net does asynch pages, which solves have of that problem at least, but there are other scenarios I've come up against. Like hitting a non-ado compatible data source. (a file or someone's linux-based web service, or you know, any number of things.) I can set it up to produce data asynchronously, but it's really no picnic not being able to use built in consumer methods like BeginExecuteReader(); which were build to support this model in conjunction with SQL server. I have since read your other articles, and I'm feeling a good deal more enlightened, but I still feel that there is a huge hole on the consumer side of all doco out there on this parallel programming push. Even the msdn blog sites seem to pretty much cover only the producer, and maybe a Console.WriteLine() to demo the fact that it's actually Asynch. I even saw the same in the CCR demos on Channel9.msdn.com. Just looking for some guidance on the other end.
Andrew StantonPosted May 17, 2007, 8:40 PM
There are a few syntax problems (result in EndFetchInt() )and it is making it difficult to trace the steps that the application is using. I understand that the context is that of event driven, but it would make it easier if you could maybe number the execution order of the lines of code, or maybe provide a graphic displaying the interaction.
Mike GoldPosted May 12, 2007, 4:06 PM
Can't tell you how many applications I've seen where the programmer just creates thread after thread. What a mess! Good advice here.