Search
Sign In
Home
Recent
Media
Videos
Podcasts
Screencasts
Learn
Shows
The Continuum Show
Going Deep
10-4
See All Shows...
Forums
Coffeehouse
Tech Off
Feedback
Sandbox
Key Topics
Visual Studio
Continuum
Identity
Interoperability
Azure
Windows
Wiki
Search
Subscribe
Posts
>
Charles
Jeffrey Richter and his AsyncEnumerator
Posted By:
Charles
|
Dec 3rd, 2008 @ 5:52 PM
|
92,329
Views |
21
Comments
Jeffrey Richter’s Power Threading Library contains his AsyncEnumerator class which uses C# iterators to allow developers to perform asynchronous operations via an easy to use synchronous programming model. For those of you who can remember
our conversations on CCR from years back
, the use of iterators in this concurrent context is at the core of CCR's implementation of asynchronous processing. The power of iterators in C# enables all of this. The CCR team was in fact the first to employ an asynchronous programming model based on C# iterators, which was a very novel use of the new feature in C# 2.0. This doesn't take away from Jeff's current excellent async implemenation (not at all - Jeff has made some real innovation here!).
Watch this Screencast produced by Developer Division Community Program Manager Charlie Calvert to learn how Jeff's library enables the creation of scalable and responsive applications with minimal resources (threads/context switches). The library discussed in this Screencast can be downloaded from
http://wintellect.com/PowerThreading.aspx
.
Tags:
AysncEnumerator
,
CCR
,
Jeffrey Richter
,
Programming
Media Downloads:
Screencast
WMV
Share:
Del.icio.us
Digg
DotNetShoutout
Facebook
FriendFeed
MSDN
Twitter
Rating:
10
1
page 1 of 3
Delete
Edit
Comment on Post
Delete
Edit
Reply
#Dec 3rd, 2008 @ 7:22 PM
Minh
WOOH! WOOH!
In reply to {0}
Download:
[Pending]
This library seems interesting. Can someone comment on similarities/differences to the Parallel.For library?
IIRC, there's no cancelling nor timeout mechanism in Parallel.For, but is that all?
Delete
Edit
Reply
#Dec 4th, 2008 @ 11:58 AM
LukePuplett
They're my own arms
In reply to Minh
#Dec 3rd, 2008 @ 7:22 PM
Download:
[Pending]
Differences with Parallel.For? One that springs to mind is that an application on current or myabe not-so current .NET technology can leverage this technique.
Top marks, Jeff.
Delete
Edit
Reply
#Dec 4th, 2008 @ 2:27 PM
JeffRichter
Jeffrey Richter
In reply to Minh
#Dec 3rd, 2008 @ 7:22 PM
Download:
[Pending]
They are very different. Parallel.For in particular is about performing a bunch of compute-bound operations in parallel scaling out across all the CPUs in teh machine. My AsyncEnumerator is mostly about issuing one or more concurrent I/O-bound operations without have any threads block for them to complete.
Delete
Edit
Reply
#Dec 4th, 2008 @ 5:21 PM
granicz.adam
Adam Granicz, IntelliFactory
In reply to {0}
Download:
[Pending]
You guys should look at asynchronous workflows in F#, here is a Channel9 video on it:
http://channel9.msdn.com/posts/Charles/Don-Syme-Whats-new-in-F-Asynchronous-Workflows-and-welcome-to-the-NET-family/
Asynchronous workflows allow you to express asynchronous computations without having to wrap their continuations.
Delete
Edit
Reply
#Dec 5th, 2008 @ 5:24 AM
danielearwicker
Isn't C# great?
In reply to {0}
Download:
[Pending]
Couldn't the function use yield return to hand back a lambda, and the lambda would contain the asynchronous call(s) to fire off?
The calls could be made on an interface that wraps the socket and hides the details of managing the asynchronous nature of the call altogether.
Hmm... this sounds like a good idea... I'll whip up something to demonstrate what I mean more clearly.
Delete
Edit
Reply
#Dec 5th, 2008 @ 6:18 AM
danielearwicker
Isn't C# great?
In reply to {0}
Download:
[Pending]
Here's what I mean:
http://incrediblejourneysintotheknown.blogspot.com/2008/12/asynchronous-sockets-with-yield-return.html
Would be very interested to hear what Jeffrey thinks about it!
Delete
Edit
Reply
#Dec 5th, 2008 @ 5:23 PM
Joseph Albahari
In reply to {0}
Download:
[Pending]
Regarding the difference between this and PFX, they are solving different problems. PFX is about providing simple means of parallel execution; Jeff's library is about maximizing thread efficiency by avoiding thread blocking altogether by following the APM model. APM is a requirement when writing programs that:
(1) have potentially hundreds or thousands of parallel execution paths
(2) spend most of their time blocking
Without (1), you won't gain enough through the APM to justify the extra programming effort. Without (2), you won't save anything with the APM. The quintessential application is a sockets server that accepts requests over the net. Because the Internet is slow, requests may take many seconds from end to end, and yet spend most of their time blocked waiting on a slow network. A well-written asynchronous TCP server can handle a thousand concurrent requests while consuming just a few threads.
APM relies on methods returning with a callback rather than blocking the underlying thread. There are actually fairly few truely asycnhronous methods in the .NET Framework - most are related to networking, where the most gains are to be had.
Jeff's idea is very clever - but it's dubious using it for retrieving web pages in the background in a Win Forms application. The only thing he's achieving is saving the overhead of tying up one or two threads for a few seconds. There was a time when tying up 1MB of memory for a few seconds was a big deal, but those days are long gone. Using PFX (or asynchronous delegates, which interestingly don't follow the APM) would be simpler and just as effective.
By far, the most common use for the async-callback-method model is writing a TCP or HTTP server capable of handling hundreds of concurrent requests. It's NOT required within ASP.NET apps because the ASP.NET infrastructure already does this for you. It's also not needed around making database calls within a web app because the DB server will nearly always be more of a bottleneck than the accompanying thread overhead. And who in real life would give up the productivity of the high-level synchronous DB libraries such as LINQ to SQL and revert to using low-level async-compliant SqlCommand objects and the like?
So if you were writing a large TCP or HTTP server from scratch yourself, Jeff's library may be very helpful. The only problem I can see (unless I'm mistaken) is that you can't refactor iterator methods into smaller chunks - as its complexity grows, the method will get bigger and bigger and there's nothing you can do about it. The problem is that any methods that you call from an iterator can't themselves yield on behalf of the caller. So if you wanted to do this:
foreach (var foo in far)
AnotherMethod (foo);
then AnotherMethod couldn't do anything asynchronous within its implementation.
Joe
Delete
Edit
Reply
#Dec 5th, 2008 @ 8:05 PM
JeffRichter
Jeffrey Richter
In reply to Joseph Albahari
#Dec 5th, 2008 @ 5:23 PM
Download:
[Pending]
I certainly agree with your comments about server-side code. However, I disagree with your thoughts about client-side code. On my machine Outlook (just to pick some app as an example) has over 50 threads in it because the Outlook developers have the mindset that it isn't bad to just spawn off a few more threads and allocate a few more megabytes of memory. However, this wastes a lot of resources and if Outlook is running on a terminal server machine hosting 100 client sessions, then that means 5,000 threads on the system! In fact, because this problem is so bad, Windows 7 is doing a lot to reduce the number of threads used throughout system services and applications that ship with the OS so that Windows 7 will run well on small footprint machines with only 1GB of RAM in them. Clearly the Windows team feels that all the threads they have been creating has been hurting them and they are finally doing something about it.
And, since I'd like to make things better for Windows users, I highly recommend asynchrounous programming for client-side applications. Also, delegates DO support the APM via their BeginInvoke/EndInvoke methods and because of this, asynchronous delegate invocations integrate quite nicely with my AsyncEnumerator. In addition, my AsyncEnumerator automatically marshals the result back to the GUI thread so there is no need to call Control's BeginInvoke method (for Windows Forms) or DispatcherObject's BeginIvoke method (for WPF). Furthermore, my AE offers cancelation/timeout support as well as discard support which are all useful features for client-side applications that you do not get with the APM alone or by just spawning up another thread.
ASP.NET does support the ability for developers to implement their web form or web service app asynchronously but few developers take advantage of this. However, ASP.NET offers it as an option because it does not simply give it to you by default. Also, it is very useful to perform async programming when accessing a DB because the DB
IS
a bottleneck (as you point out). If you make synchronous requests to a DB then your server will create a ton of threads which are all blocked; your server will handle just a few concurrent requests and memory consumption will be very high with thread stacks which your code is not using at all.
In the real world, there are many developers who will avoid high-level synchronous libraries in order to gain scalability. I know that MS does avoid synchronous DB access for Hotmail and many of its other highly-scalable services. However, it is true, that if your service has few concurrent users, then you do get a lot of benefit from various synchronous abstractions (like Linq to SQL). In an ideal world, these abstractions that offer such productivity will offer asynchronous ways of using them. Linq to SQL doesn't offer this today but it could in the future (or Linq to Entities could).
And, as for refactoring...Iterators do offer some challenges here, I agree. However, from an iterator, you can call compute-bound synchronous methods or methods that initiate an asynchronous compute-bound or I/O-bound operation that itself returns an IAsyncResult. And, also my AsyncEnumerator does support composition where an iterator can invoke another iterator. For example, you could create an iterator that asynchronously queries a web server to get some data and process it. And then, you can create another iterator that consumes the first in a loop to do asynchronous processing for several web sites. In fact, all of this processing can happen concurrently allowing for phenominal scaling. If your iterator methods get overwhelming, then you can resort to call back methods which is what all native applications have to do and what developers writing scalable managed application have to do today. Iterators give you a new ability; they don't take away any of the old abilities. This ability has very few drawbacks but if you come across one, then don't use it; go back to an older tried and true way.
Delete
Edit
Reply
#Dec 6th, 2008 @ 2:02 AM
StrongCoffee
In reply to {0}
Download:
[Pending]
Very very nice. Hats off to Jeff for this.
page 1 of 3
Delete
Edit
Comment on Post
Posts
>
Charles
>
Jeffrey Richter and his AsyncEnumerator
Be the first to comment!
Reply
Reply to root
In reply to {0}
Start related discussion
Forum:
Site Feedback
Tech Off
The 9 Guy Around The World
The Coffeehouse
Subject:
Tags
*Loading available tags