Using .NET 4.0 Tasks with the AsyncEnumerator

I’ve been doing a lot of work with the new Task class that ships with .NET 4.0 as I’ve been revising my CLR via C# book (due out in early 2010).

Task are really good for performing asynchronous compute-bound work and while my AsyncEnumerator was really designed for performing I/O-bound work using the CLR’s APM, it is possible to use Tasks with the AsyncEnumerator giving you the ability to easily perform I/O-bound as well as compute-bound work and use the AsyncEnumerator to coordinate it all.

 

For example, you might want to read a bitmap image into memory from disk or network asynchronously (this is I/O bound) and then use Tasks to produce one or more thumbnail images (this is compute-bound) and then write the thumbnail images back to disk/network (I/O-bound again).

To use Tasks within an AsyncEnumerator, just create the Task(s) as you normally would and add a ContinueWith task that simply calls AsyncEnumerator’s End method to get a delegate. Then, invoke this delegate passing the task itself (since Tasks implement the IAsyncResult interface). Or, if you don’t need to identify the task, you can simplify the code some and just pass null. On the other side of the yield return statement, you need to call AsyncEnumerator’s DequeueAsyncResult to remove the entry from the AsyncEnumerator’s IAsyncResult collection but then there is no EndXxx method to call.

 

Here is a simple example, that starts a Task that sleeps for 10 seconds and then returns the current DateTime.

 

private static IEnumerator<Int32> AsyncEnumeratorAndTasks(AsyncEnumerator ae) {

   var t = new Task<DateTime>(() => { Thread.Sleep(10000); return DateTime.Now; });

   t.Start();

 

   // The Task tells the AsyncEnumerator when it is done

   // If you don’t need to identify the Task, you can pass ‘null’ instead of ‘task’

   t.ContinueWith(task => ae.End()(task));

 

   yield return 1;      // Waits for the 1 Task to complete

 

   // You MUST call DequeueAsyncResult to Remove the entry form the AsyncEnumerator object’s collection

   // Casting the return value and assigning to ‘t’ is not necessary; since ‘t’ already refer to the same Task object

   t = (Task<DateTime>) ae.DequeueAsyncResult();        

 

   Console.WriteLine(t.Result);     // Shows the DateTime when the Task completed
}

 

— Jeffrey Richter (https://training.atmosera.com)

 

 

Jeffrey Richter

View Comments

  • What if instead of IEnumerator we would return IEnumerable>?
    We could say what exactly are we waiting for (:

  • Why can't we simply have t.ContinueWith(_ => Console.WriteLine(_.Result)) in the first place?
    For IO bound operations one can use the Task.Factory.FromAsync extensions to get a suitable Task.

Recent Posts

8-Step AWS to Microsoft Azure Migration Strategy

Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…

3 days ago

How to Navigate Azure Governance

 Cloud management is difficult to do manually, especially if you work with multiple cloud…

1 week ago

Why Azure’s Scalability is Your Key to Business Growth & Efficiency

Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…

3 weeks ago

Unlocking the Power of AI in your Software Development Life Cycle (SDLC)

https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…

1 month ago

The Role of FinOps in Accelerating Business Innovation

FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…

1 month ago

Azure Kubernetes Security Best Practices

Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…

2 months ago