Jeffrey Richter and his AsyncEnumerator
- Posted: Dec 03, 2008 at 5:52 PM
- 101,164 Views
- 21 Comments
Loading User Information from Channel 9
Something went wrong getting user information from Channel 9
Loading User Information from MSDN
Something went wrong getting user information from MSDN
Loading Visual Studio Achievements
Something went wrong getting the Visual Studio Achievements
Right click “Save as…”
Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation,
please create a new thread in our Forums,
or
Contact Us and let us know.
Follow the Discussion
Oops, something didn't work.
What does this mean?
Following an item on Channel 9 allows you to watch for new content and comments that you are interested in. You need to be signed in to Channel 9 to use this feature.What does this mean?
Following an item on Channel 9 allows you to watch for new content and comments that you are interested in and view them all on your notifications page.sign up for email notifications?
IIRC, there's no cancelling nor timeout mechanism in Parallel.For, but is that all?
Top marks, Jeff.
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.
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.
http://incrediblejourneysintotheknown.blogspot.com/2008/12/asynchronous-sockets-with-yield-return.html
Would be very interested to hear what Jeffrey thinks about it!
(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.
foreach (var foo in far)
AnotherMethod (foo);
then AnotherMethod couldn't do anything asynchronous within its implementation.
Joe
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.
Nice to hear from you! Regarding Outlook, I agree that spawning 50 threads is way over the top. There's a difference, though, between consuming 50 threads for the life of the application and starting two threads that will run for a second.
I wonder what Outlook is doing to consume that many threads. I never would have imagined that checking one's e-mail was that complicated!
Cheers
Joe
I find this quite useful and it probably does make developing code faster in some circumstances.
Thanks Jeff
I do have one question though Jeff, you used to make the source code for your async library available on Wintellect, but now you only release a compiled library. Why is this? I have found that the latest release has caused a breaking change to my code, and so I am still using the version from May. Can you at least outline what has changed between that version and Octobers release?
Steve
www.codeproject.com/KB/cs/AsynchronousCodeBlocks.aspx
This library with my accompanying Managed IOCP library were very similar to Microsoft's Parallel FX and Task Library. I wrote these libraries in Mid 2005 through 2006.
Regards,
Aditya.P
(Be Original)
Various channel9 videos and PDC talk have examples...
http://channel9.msdn.com/pdc2008/TL55/
http://channel9.msdn.com/tags/CCR/
CCR example for file read (from PDC session):
IEnumerator<ITask> CcrReadFileAsync(string file)
{
var result = new Port<IAsyncResult>();
using (var fs = new FileStream(file,…,FileOptions.Asynchronous))
{
var buf = new byte[fs.Length];
fs.BeginRead(buf, 0, buf.Length, result.Post, null);
yield return result.Receive();
var ar = (IAsyncResult)resultPort.Test();
try {
fs.EndRead(ar);
ProcessData(buf);
} catch { // handle exception }
}
}
In this case, Jeff has extended on the basic functionality present in CCR's implementation of async using C# iterators to include some new and powerful capabilities. Great work, Jeff!
C
Thank you my dear friend. I like you and your books.............
When would you use the CCR versus this?
Hi Jeffrey,
I wanted to show your video about the AsyncEnumerator to a colleague, but it seems to have disappeared from Channel9...
Was that a result of a conscious action, or did something go wrong? Is there any other place I can find it? - Peter
Fixed. Thanks for letting us know!
C
This seems to be an implementation of trampoline-style threading in .Net.
You write your code as a method which periodically gives up control of its calling thread by use of the "yield" statement. And you expect that the scheduler/engine will revive you so that you can continue from where you left off.
This same technique can be used to write multi-threaded programs in single-thread languages such as javascript: http://blog.monstuff.com/archives/000315.html
This technique would benefit from C# supporting the "yield foreach" construction. This would allow for an iterator method calling into another iterator method passing the result directly through. This is an especially useful syntax and optimization for recusive calls (tree navigation).
Read more on "yield foreach" at http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx
Remove this comment
Remove this thread
close