简体   繁体   中英

Do we still need Richter's AsyncEnumerator?

Recently I stumbled across the AsyncEnumerator class form Jeffrey Richter's Power Threading Library which seems to solve several problems I'm usually encountering when programming asynchronous stuff.

The idea for this class has been around for quite a while now and I'm wondering if current versions of .NET / C# have built-in support for this mechanism by now or if it is still necessary to rely on a third party library? Or maybe newer versions of .NET have some alternative approach which simplifies asynchronous programming as much as Richter's AsyncEnumerator does?

Or in other words: Is there a reason to not start using Richter's AsyncEnumerator today?

Edit:

Some links with information on AsyncEnumerator:

Yes, you will still benefit from my AsyncEnumerator. The new threading stuff introduced in .NET 4 (Tasks, Parallel, PLINQ, etc), is all about concurrency. That is, they are all about taking a computational workload, dividing it up and spawning it out onto multiple threads so that the workload can complete in less time than it would takes 1 thread to do the entire workload. You can use these constructs to execute multiple synchronous I/O operations concurrently. However, the synchronous I/O operations cause all the threads to block which then causes the threadpool to create more threads. And so, your app's resource usage skyrockets while your CPU usage remains very low. This is a very inefficient to implement your application and prevents your app from scaling.

My AsyncEnumerator is all about initiating asynchronous I/O operations without blocking any threads so that your app's resource usage remains very low so your app scales very well. CPU usage remains low in this case too because you are performing I/O; not a computational workload.

In the next version of .NET, the new async/await language features (which I worked on with Microsoft), enables you to perform async I/O and in fact, the new features are modeled very similar to my AsyncEnumerator. So much so that you can port code that uses my AsyncEnumerator to the new model with very few source code changes.

As someone else pointed out, my AsyncEnumerator still offers other features and works with .NET 2.0 and later. So, many people will still find it quite useful for a long time.

An obvious parallel here is PLINQ, but Richter himself dismisses this :

Jeffrey Richter Dec 04, 2008 at 2:27 PMquotereply 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.

However, the C# async CTP may be useful here, making thread continuations much more reasonable, ie

var bytesRead = await stream.ReadAsync(...);
Console.WriteLine(bytesRead); // woah! we're on a different thread now!

Here, the C# compiler re-writes everything around await instuctions, such that it becomes a callback/continuation to the existing async operation (which must return an "awaitable" value). Once this is in production, I hope this will become a much more natural way to write code with intrinsic delays due to async.

.net 4.0 includes the PLINQ framework and various other means of threaded computation.

See Parallel Programming in the .NET Framework for more details.

From this question Asynchronous iterator Task<IEnumerable<T>> :

It sounds like what you may really be looking for is something like IObservable<T> , which is sort of like a push-based asynchronous IEnumerable<T>. See Reactive Extensions, aka Rx from Microsoft Open Technologies (code licensed under Apache-2.0) (no affiliation) for a huge host of methods that work with IObservable<T> to make it work like LINQ-to-Objects and more.

The problem with IEnumerable<T> is that there's nothing that really makes the enumeration itself asynchronous. If you don't want to add a dependency on Rx (which is really what makes IObservable<T> shine), this alternative might work for you:

public async Task<IEnumerable<char>> TestAsync(string testString)
{
    return GetChars(testString);
}

private static IEnumerable<char> GetChars(string testString)
{
    foreach (char c in testString.ToCharArray())
    {
        // do other work
        yield return c;
    }
}

though I'd like to point out that without knowing what's **actually being done asynchronously, there may be a much better way to accomplish your goals. None of the code you posted will actually do anything asynchronously, and I don't really know if anything in // do other work is asynchronous (in which case, this isn't a solution to your underlying problem though it will make your code compile).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM