Ziff-Davis Enterprise 
DevSource: Microsoft Developer Resource
Add OnsArchitectureLanguagesTechniquesUsing VSForums
 
Home arrow Using VS arrow Page 2 - Why Asynchronous Delegates Are Your Friend
Why Asynchronous Delegates Are Your Friend
By Jon Shemitz

Rate This Article:
Add This Article To:
Why Asynchronous Delegates Are Your Friend - ' What'
( Page 2 of 4 )

's it For?">

Many practicing .NET programmers do not know that any delegate can be invoked asynchronously. The syntax involves a strange and confusing pair of (usually) null parameters. Most people see that and immediately put it on the "some other day" pile, which of course gradually becomes the "never" pile. But it is true: any (singleton) delegate can be invoked asynchronously.

Asynchronous invocation is a good way to pass parameters to a (reusable) ThreadPool thread, and to get results back. For example, a delegate that takes a string and returns a string may be reading a large file, or may be downloading a URL. When you start a delegate running asynchronously, it runs in a ThreadPool thread until the delegate returns. The thread that spawned it can do as much as it can until it needs the value the delegate returns, at which point it can either block by calling EndInvoke or do arbitrarily complicated things with the IAsynchResult wait handle.

ADVERTISEMENT

Asynchronous invocation is not the only way to pass parameters to a (reusable) ThreadPool thread. To pass parameters to a fire-and-forget method, ThreadPool.QueueUserWorkItem is a good way to run an anonymous method that doesn't return a value. One example would be saving a large string to a file; this either succeeds (and nothing more need be done), or it fails ands get logged (and nothing more need be done). The anonymous method automatically captures the state it needs, and you don't have to EndInvoke a user work item the way you have to EndInvoke each asynchronous delegate call.

Conversely, if you want to get a result back from a threaded agent, asynchronous delegates are the way to go. This is a 1.0 feature which has gotten even more appealing in 2.0, with its expanded range of delegates.

When you call a delegate as it were a normal method — such as double Result = Fn(46D) or Callback(PercentComplete) — you are making a synchronous call. The compiler turns what looks like a method call into a call to the delegate instance's CLR generated Invoke method, which takes the same parameters as the delegate. The Invoke method executes each method on the delegate's invocation list in the current thread, and control doesn't return to the delegate's caller until Invoke has executed each method on the invocation list.

If a delegate only has a single method on the invocation list (normally this means that you got the delegate from a new delegate operation, not from Delegate.Combine) you can also execute the delegate asynchronously. That is, in addition to the synchronous Invoke, every delegate has two asynchronous methods: BeginInvoke and EndInvoke. (All these delegate invoke methods are runtime methods, which are generated by the CLR on first call, instead of being jitted from CIL.) You can call BeginInvoke to run the delegate in a ThreadPool thread, do some other work in the current thread, and then call EndInvoke to collect the delegate's results. (I talk about the system ThreadPool in the other half of this pair of articles.)

Asynchronous invocation is a rather advanced technique, but you might use it any time an IO-bound method is just one of the inputs that you need before you can perform some task. For example, you might need to read a file and initialize some complex data structures before you can call some method. Rather than read the file and then do the computations, you can BeginInvoke a delegate to the method that reads the file, and do some (or all) of your other setup during the milliseconds that file IO spends waiting for interrupts from the disk controller. Similarly, if you need to read two (or more) files, you could BeginInvoke delegates that read each file to a string, do as much else as you can, and then call each delegate's EndInvoke to collect the file contents at the point you actually need it. At least conceivably, the operating system can optimize disk access so that reading files in parallel is faster than reading them sequentially.

On hyperthreaded and/or multicore machines, you can use asynchronous invocation to parallelize. Instead of doing something to each list item one after the other in a big foreach loop, a foreach loop can grab a reusable ThreadPool thread for each item, and use a Semaphore to keep the number of active threads in balance with the number of processors.



 
 
>>> More Using VS Articles          >>> More By Jon Shemitz
 



DevSource video
Devsource Video Series
Manipulating Society through Technology
Jeremy Bailenson, Director of the Virtual Human Interaction Lab at Stanford University, talks about virtual reality, avatars, Moore's law, how real world behaviors influence online reality, and societal manipulation through technology!
>> Play video
>> Read article
>> See all videos
DevLife Blog

Julia explores the Robotics Studio! (It's for more than you think.)

MSDev Blog

Messages for Bill Gates!

Make it Work
.NET makes runtime type checking a breeze. See what Peter has to say about it in this week's tips!
News
Microsoft Counts on App Support for Vista
Microsoft has taken pains to demonstrate that Windows Vista will have ample application support.
DevSource RSS FEEDS
XML Want an easy way to keep up with breaking tech news? And the Get DevSource headlines delivered to your desktop with RSS.