Posts Tagged ‘asynchronous’
MindTouch Coroutines and C#5.0 async
This week, at PDC 2010, Anders Hejlsberg introduced what is to become C# 5.0 and it’s major new feature: Making Async easy. The main facility for achieving this goal is the language keyword pair or async and await. Together they allow synchronous methods to be called in an asynchronous way without having to jump through all sorts of hoops.
This is very exciting stuff for us here at MindTouch, since we’ve built almost exactly that facility with our Asynchronous Method Pattern and Coroutine infrastructure in DReAM. But the one thing that has always bothered us what the additional manual code and sometimes unintuitive syntax required.
The Result and Task based asynchronous patterns
Steve Bjorg introduced Result<T> with DReAM on top of the .NET 2.0 and mono 1.1.16 back in 2006. You can find a quick overview of it here. I've also covered it extensively in my monoconf talk. It's is similar in purpose to the Task class in the Task Parallel Library introduced by Microsoft in .NET 4.0. Both of them are a kind of future, a handle for a value that may or may not have been produced yet. Both provide asynchrony patterns for easily calling a method that promises to produce a result eventually.
The MindTouch Asynchronous Method Pattern (AMP) takes this form:
Result<T> MethodName(...input paramaters..., Result<T> result)
where the trailing Result<T> is used to set up conditions on the return value, such as Timeout.
The Task-based Asynchronous Pattern (TAP) looks like this:
Task<T> MethodNameAsync(...input paramaters...)
Both are easy enough to call in blocking form, but that defeats their purpose. Both could also be set up with continuation handles, which get executed once a value T is available, but that takes the return code out of the current flow. And as completions call other asynchronous methods, your code just wanders off the right-hand side of the screen. This is common problem with continuations and is both a aesthetic and readability problem, in that your logically linear (if non-blocking) execution flow becomes increasingly difficult to follow.
Simplifying async flow with MindTouch Coroutines
What would be really nice is being able to call an asynchronous method and write the code that deals with the result on the next line, while simultaneously having your code suspend itself, freeing up your thread while the asynchronous code completes.
One way to approach this is with coroutines, i.e. a method that can exit and resume multiple times, rather having only one entry point. A coroutine can yield control to the async method and resume after it completes. In .NET 2.0 the yield operator was added to C# for the iterator pattern. If you turn the iterator pattern upside down, you end up with a method that yields not iteration results but continuations to some engine executing the control flow, i.e. MindTouch Coroutines:
Result<XDoc> r; yield return r = Download(uri, new Result<XDoc>); var doc = r.Value;
This provided us with the ability to write methods in synchronous style that could call to potentially long running asynchronous processes but continue their linear flow without ever blocking the thread. For a more detailed look at how coroutines are implemented check this article. However, the cost of achieving this came with some syntactic artifacts.
As illustrated above, we can't declare and assign the result type T in the yield return, hence the pre-declaration of Result<XDoc> r and the trailing var doc = r.Value. Three lines instead of one. In C# 3.0, using Lambdas, we reduced this to two lines:
XDoc doc; yield return doc = DownloadAndProcess(uri, new Result<XDoc>).Set(v => doc = v);
Another artifact is that a coroutine has to return an enumerator. We use IYield, which Result implements and coroutines require the return type IEnumerator<IYield> and by convention use a Result<T> as their last argument. That means coroutines can yield AMPs but are not AMPs themselves. As I stated above, a coroutine is an iterator turned upside down, yielding control to some executing engine. This means that every AMP that uses a coroutine can be written using this convention:
Result<XDoc> DownloadAndProcess(XUri uri, Result<XDoc> result) {
return Coroutine.Invoke(DownloadAndProcess_Coroutine, uri, result);
}
IEnumerator<IYield> DownloadAndProcess_Coroutine(XUri uri, Result<XDoc> result) {
XDoc doc;
yield return Plug.New(uri).Get(new Result<DreamMessage>)
.Set(v => doc = v.ToDocument());
// do some more async work
result.Return(doc);
}
Note: I snuck in Plug here, which is our fluent interface wrapper around HttpWebRequest and implements the AMP, internally using the async interface of HttpWebRequest, i.e. we can yield a Plug.Get and it will resume execution once the request completes.
C# 5.0 async/wait continuation flow
With C# vNext, Microsoft introduces two new language keywords that basically let you create the same flow we provide via the AMP and Coroutines, but using Task and leaving the syntactic cost to the compiler instead. This means that the TAP can be used without having to define a custom method with a different signature to execute the async work flow:
async Task<XDoc> DownloadAndProcess(XUri uri) {
var doc = await Plug.New(uri).Get();
// do some more async work
return doc;
}
The async keyword marks the method as one that the compiler needs to rewrite a sequence of continuations. The await keyword tells the compiler that a TAP method is being called and to squirrel the rest of the method body into a continuation that is executed once the Task<XDoc> has a result. Here the compiler takes on the work of letting you use a single method signature to call either as a regular method or as source of a continuation and rewrites a TAP call to yield execution flow and resume after completion. Using async/await certainly reduces ceremony and makes it all more readable. We wish we could have had that luxury when we embarked on this pattern 4 years ago. Note: The above code pre-supposes a version of Plug that implements the TAP instead of the AMP.
yield vs. await vs. something else
Shortly after Anders' PDC talk Eric Lippert posed the question whether await is the best name for this new facility in the post Asynchronous Programming in C# 5.0 part two: Whence await? on his blog. The comment thread is a good read of arguments for and against various keywords. Personally being partial to yield, I read Jon Skeet's case against it in his post C# 5 async and choosing terminology: why I'm against "yield" with interest. His point is that "[w]hen the action completes very quickly and synchronously, it isn't yielding at all." My personal feeling is that whether or not the call returns very quickly is an implementation detail invisible to the caller. The caller is yielding control to the callee, who makes the decision whether to return immediately or suspend the caller until completion.
However await does seem like the least appropriate of the options, since we're really not waiting at all. Syntax like continue after, continue with and continue when certainly seem more appropriate and descriptive of the action taking place. While yield return perfectly describes to me what happens, maybe that is a sign the terminology reveals the implementation detail rather than the intent. The caller doesn't care about the yielding of control. The caller just wants the result from the call and get on with its business. So from a clarity of code perspective, I have to side with the continue (after|with|when) camp.
When can I use async/await?
The CTP is available now. Of course, there is no release date, taking a gaming industry "when it's done!" stance. My bet is that async/await will be usable in the next mono release (2.10? 3.0?) before C# 5.0 ships. Any way you look at it, though, it's going to be a while before you can rely on it existing on a platform you didn't personally configure.
In the meantime, DReAM coroutines are battle tested, powering all REST services in the MindTouch product and any other product using DReAM, and you can be sure that as C#5 approaches we will be tracking its progress closely to evaluate using the TAP in DReAM. We certainly would love to take advantage of the simplified syntax, while staying compatible with our existing syntax.
Concurrent Podcast (Episode 3): Coroutines
Photo by ToniVC
Concurrent Podcast 03: Coroutines
One topic we’ve mentioned in both previous episodes is Coroutines. We use them extensively at MindTouch and the asynchronous programming model provided by the Dream framework fundamentally relies on them. Since we’re likely to keep bringing them up in the future, we thought it best to cover them sooner rather than later.
For some background reading on Coroutines in C# check out my previous article corporate blog or the same content as a tutorial on the developer site (better code formatting).
As usual, you can find future topic listed here, and we always welcome suggestions on what should take precedence or what other topics to cover. If you want to subscribe to just the podcasts, you can find the feed here.
Concurrent Podcast (Episode 2): Why Async matters
Concurrent Podcast 02: Why Async
In Dream and MindTouch 09, we try to follow an async pattern using our own Coroutine framework throughout all systems. This is necessitated by an architectural decision that components of the system are decoupled to use the Http Request/Response pattern between each other. While we optimize for calls within the system to never hit the wire, it is fundamentally constructed so that any component could live across a wire boundary. This means that calls between components could leave the current process. Traditionally that kind of call would block the calling thread. Since this is central to our pipeline, that blocking would drastically reduce the capacity of any install. By using asynchronous calls, we never block, but instead yield the current thread to do some other work while we wait for a response.
Clearly, we’re highly invested in async, but we started having discussion internally why should other programmers care about this pattern. It does add complexity, so is it really a case of YAGNI?
Episode 2 is a product of this debate. We try to cover the use cases developers presently encounter and the ones that are on the horizon, becoming central to future development. We also talk about the complexities and pain involved given the present tooling and infrastructure. We hope that our discussion will give you useful information as you venture into asynchronous programming.
As a sidenote, for Episode 2, we also tried out a different recording setup which did not work out all that well. Apologies for the sound quality this week; we’re still learning the best way of doing this and hope to have significant improvements in place for Episode 3.
As usual, you can find future topic listed here, and we always welcome suggestions on what should take precedence or what other topics to cover. If you want to subscribe to just the podcasts, you can find the feed here.
Async I/O: Dream vs. Parallel Extensions
We’ve been following the Parallel Programming with .NET blog pretty closely and are excited about what the Task Parallel Library and PLINQ will bring to .NET 4.0. A lot of the problems they are addressing are the same that we’ve faced for a while, which was the motivation for us to create Dream in the first place.
Yesterday, the Parallel Programming with .NET blog posted an article entitled “Parallel Extensions and I/O” illustrating how to use Parallel Extensions to asynchronously retrieve a number of resources located at the end of a Uri. Dealing with web resource being one of the primary purposes of Dream, we thought it would be interesting to show the simple and compact syntax you can use with Dream right now to achieve the same result.
I will cover their approach briefly for contrast, but you should read their article first to get an understanding of the problem and the proposed solution. Here’s the scenario in a nutshell. We have list of Uris for web resources like this:
static string[] Resources = new string[] {
"http://www.microsoft.com", "http://www.msdn.com",
"http://www.msn.com", "http://www.bing.com"
};
And we want to parallelize fetching these resources and do so asynchronously. The final result should be a collection of byte arrays, one for each resource.
In Dream, we have wrapped HttpWebRequest with a class called Plug, which provides a fluent interface for defining web requests and retrieving data. For a more indepth look at Plug, you should read Consuming REST services and TDD with Plug.
Instead of using an async callback pattern for Plug, we use the Dream Result<T> object, which functions as a completion handle. In the case of Plug, the return of .GetAsync() is a Result<DreamMessage>, where DreamMessage is a representation of the Http response with built-in conversion into common data types such as Text, Xml, or bytes. This means we can fire off a number of asynchronous requests, collect all their Result objects and then iterate over them, waiting for their completion.
Given this infrastructure, we can write two simple LINQ expressions to execute this work:
// first, we start all requests asynchronously // (the ToArray() forces immediate execution) Result<DreamMessage>[] requests = (from resource in Resources select Plug.New(resource).GetAsync()).ToArray(); // second, we block on each result objects until it has completed // and convert the response into a byte array byte[][] data = (from request in requests select request.Wait().ToBytes()).ToArray();
The trick in the above code is the lazy execution of LINQ. I.e. the first expression sets up a select that fires off all requests asynchronously. However, no attempt to start the asynchronous requests is made until we iterate over the returned IEnumerable. By using .ToArray(), we force immediate execution, which still returns immediately, since each execution runs asynchronously.
Had we called Plug.GetAsync().Wait() instead of splitting Plug.GetAsync() and .Wait() into two steps, each request would have had to wait until the previous one had finished before the next one would be issued. However, in the above approach, the first .ToArray() starts all the requests, while the second .ToArray() waits on each result objects until all have completed their requests. Note that completion, in this case, includes reading the response message asynchronously as well. Hence, we get the absolute lowest possible overhead for achieving our goal with very little code!
With Plug doing the heavy lifting, asynchronous execution of web calls becomes very simple and, best of all, it’s available today in Dream under the Apache 2.0 license.
Consuming REST services and TDD with Plug
If you’ve ever used HttpWebRequest in .NET you’ve probably thought to yourself: man, there’s got to be an easier way! Sure, for the most simplistic uses, you can always fall back on WebClient, but now you have two different models for Web requests which doesn’t improve your code’s maintability, nor your sanity. And forget about testing.
Plug, XUri and XDoc
Since MindTouch Dream–the foundation for MindTouch 2009–has a strong REST services focus, one of the central requirements was making http handling clean and painless. To this end Dream includes a class called Plug (think Socket) to wrap HttpWebRequest (et al.). Two additional pain points with doing web requests are building Uri’s without resorting to string parsing and concatenation and building and processing Xml for request and response payloads. Dream offers, respectively, XUri and XDoc, to assist Plug.
All three provide fluent interfaces for construction and manipulation. In addition, XUri and Plug are immutable, meaning that the return value of each fluent interface call returns a new instance with the requested modification without changing the original. Simply this means that you can do things like this:
XUri serviceBase = new XUri("http://foo.com/api");
XUri authUri = serviceBase.At("authenticate");
XUri profileUri = serviceBase.At("users",userId,"profile");
XDoc on the other hand does modify an underlying document, so a modification does alter the document. To create a new document, the original has to be explicitly cloned. The main benefit of XDoc is simple creation and querying of Xml:
XDoc doc = new XDoc("user")
.Attr("id",123)
.Attr("href","http://foo/api/users/123")
.Elem("name","joe")
.Start("groups")
.Elem("group","admin")
.Elem("group","contributor")
.End();
// iterate over groups in doc using XPath
foreach(XDoc group in doc["groups"]) {
Console.Writeline("group: {0}",group.AsText);
}
Fluently making WebRequests
Now that we can build Uris and documents and know how to examine request documents, the only thing left is making the request, which is as simple as:
XDoc users = Plug.New(usersUri)
.With("limit",10)
.WithHeader("X-Auth","asdfg")
.Get()
.AsDocument();
This is an example of synchronously retrieving the Uri userUri with a query argument of limit=10 and an authentication header of Xauth: asdfg (Dream also allows the same to be done asynchronously). Up to Get(), we’re constructing the Plug. After that we are actually dealing with a response object of type DreamMessage which contains both headers and body. The AsDocument() method returns the DreamMessage body as an XDoc instance which we can then inspect using XPath.
And that’s all there is to web requests using Plug. The class contains a number of extra methods for doing GET, PUT, POST, DELETE, etc., synchronous and asynchronous calling conventions, header and query arg manipulation, etc. Even doing a application/x-www-form-urlencoded POST is as simple as stringing together the name value pairs:
formPlug.With("key1",value1").With("key2","Value").PostQuery();
Since application/x-www-form-urlencoded is just a list of key/value pairs, similar to the Uri querystring, Plug provides PostQuery() as a method to convert the query args into a Post body and submit them. Of course, you can still use With() for query args and the regular Post() method with a manually specified POST body, if you need both query and post key/value pairs.
Testing your Service Consumer
Now that web requests are simple, you can concentrate on your application code, rather than having to worry about constructing and dealing with HttpWebRequest. But what if you want to make sure that your application code is correct without having to rely on the service you call?
Testing against a live web service is always problematic, especially if its not a service you control:
- You can’t control whether it’s up and responsive
- You may need some setup before you can make the call you want to test, such as authentication or creating a test resource, adding noise and unrelated sources of failure to your test
- When a failure occurs you don’t know for sure whether you did something wrong or if the service had a hicup
- Unless the service you are consuming offers a test server, you will be mixing test and live data
- If the service provides data to you that you didn’t create (such as an RSS feed), testing whether you can handle that data relies on it being available to you at test time
And the list goes on…
You could always write a wrapper around your service calls, and if you’ve been using HttpWebRequest you’ve probably already done this, both to factor its complexity into a simpler re-usable component and for the ability to mock it out. But taking that approach means you have to dummy down the ease and expressive power of Plug to a mockable interface. Mocking Plug itself isn’t really an option, but even if it was, you’d basically be re-implementing it to get the full api.
This complexity of mocking is commonly perceived as a problem of fluent interfaces. However, most fluent interfaces themselves are not business logic but an access abstraction to an underlying resource. In our case the underlying resource is an http request. So what we really wish to mock is the request, not Plug, allowing us to use Plug directly in our business logic without sacrificing testability.
AutoMockPlug
Dream contains a simple Arrange, Act and Assert mocking harness for Plug. It allows you to set up an interceptor for a base Uri, arrange expectations for calls, and assert that the expectations were met after the desired actions were taken.
Let’s assume we have some repository in our API to retrieve users from the REST service and the repository will automatically authenticate if a call fails as Unauthorized. A test of our repository’s auto-authenticate might look like this:
[Test]
public void GetUser_reauthenticates() {
First we set up the AutoMockPlug expectations and responses, i.e. the calls we believe our code should make across the wires and what it expects to get back. This is done with the mock.Expect() fluent interface:
// -- Arrange --
AutoMockPlug mock = MockPlug.Register(baseUri);
// expect a call to retrieve user xml, but respond with unauthorized
mock.Expect().Verb("GET").Uri(baseUri.At("users", userName))
.Response(new DreamMessage(DreamStatus.Unauthorized, null));
// expect a call to authenticate for user/pass and return an auth token
mock.Expect().Verb("POST").Uri(baseUri.At("authenticate"))
.RequestDocument(new XDoc("authenticate")
.Elem("user", userName)
.Elem("password", password))
.ResponseHeader("X-Auth", authToken);
// expect another call to retrieve user xml, make sure the authtoken was passed
// and return user doc (abbreviated here for display purposes)
mock.Expect().Verb("GET").Uri(baseUri.At("users", userName))
.RequestHeader("X-Auth",authToken)
.Response(DreamMessage.Ok(new XDoc("user").Elem("username",userName)));
Next we call the function on our object that we want to test, which in turn should be making the expected Plug calls:
// -- Act --
IUser user = repository.GetUser(userName);
Finally, we assert the final state of our test to make sure everything ran correctly. Since Plug calls may be asynchronous, AutoMockPlug uses a reset event signaled method to wait for all expectations (which also has the effect that extra calls via Plug are caught as expectation violations as well):
// -- Assert --
Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1)),
mock.VerificationFailure);
Assert.AreEqual(userName,user.Name);
}
In general, AutoMockPlug is created by registering a base Uri for interception, after which all child Uris are routed to the mock Plug. It works on the basis of ordered call expectations, checking both that the call occurred and that it meets the specified criteria. Specifying criteria and return values can be done either by the fluent interface shown in the above example, or by providing a request delegate that provides more finegrained control over the expected behavior.
Consuming the web
There’s an ever growning number of RESTful and other web services available to be consumed by your application. For example, virtually anything you can do inside of MindTouch 2009, you can also access and manipulate using Http web requests. We use Plug extensively internally to communicate between our own services and external services and generally each service call with Plug comes down to a single line of code.
The great thing about Plug is that while it’s an internal piece of plumbing for inter-service communication, it works just as simply on its own for anyone who needs to deal with web resources. And with the addition of mocking, you also get the ability to easily verify that your logic is sound before ever hitting the wire.
Plug and everything it relies on are part of the mindtouch.dream.dll and is released under the Apache 2.0 license. You can find as part of your MindTouch 2009 install or can get separately from sourceforge. For the fluent interface version of AutoMockPlug, you currently have to get trunk from svn (which does include built binaries). It will be part of the Dream 1.6.1 maintence release.

