Java Equivalent of C# async/await? - c#

I am a normal C# developer but occasionally I develop application in Java. I'm wondering if there is any Java equivalent of C# async/await?
In simple words what is the java equivalent of:
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
var urlContents = await client.GetStringAsync("http://msdn.microsoft.com");
return urlContents.Length;
}

No, there isn't any equivalent of async/await in Java - or even in C# before v5.
It's a fairly complex language feature to build a state machine behind the scenes.
There's relatively little language support for asynchrony/concurrency in Java, but the java.util.concurrent package contains a lot of useful classes around this. (Not quite equivalent to the Task Parallel Library, but the closest approximation to it.)

The await uses a continuation to execute additional code when the asynchronous operation completes (client.GetStringAsync(...)).
So, as the most close approximation I would use a CompletableFuture<T> (the Java 8 equivalent to .net Task<TResult>) based solution to process the Http request asynchronously.
UPDATED on 25-05-2016 to AsyncHttpClient v.2 released on Abril 13th of 2016:
So the Java 8 equivalent to the OP example of AccessTheWebAsync() is the following:
CompletableFuture<Integer> AccessTheWebAsync()
{
AsyncHttpClient asyncHttpClient = new DefaultAsyncHttpClient();
return asyncHttpClient
.prepareGet("http://msdn.microsoft.com")
.execute()
.toCompletableFuture()
.thenApply(Response::getResponseBody)
.thenApply(String::length);
}
This usage was taken from the answer to How do I get a CompletableFuture from an Async Http Client request?
and which is according to the new API provided in version 2 of AsyncHttpClient released on Abril 13th of 2016, that has already intrinsic support for CompletableFuture<T>.
Original answer using version 1 of AsyncHttpClient:
To that end we have two possible approaches:
the first one uses non-blocking IO and I call it AccessTheWebAsyncNio. Yet, because the AsyncCompletionHandler is an abstract class (instead of a functional interface) we cannot pass a lambda as argument. So it incurs in inevitable verbosity due to the syntax of anonymous classes. However, this solution is the most close to the execution flow of the given C# example.
the second one is slightly less verbose however it will submit a new Task that ultimately will block a thread on f.get() until the response is complete.
First approach, more verbose but non-blocking:
static CompletableFuture<Integer> AccessTheWebAsyncNio(){
final AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
final CompletableFuture<Integer> promise = new CompletableFuture<>();
asyncHttpClient
.prepareGet("https://msdn.microsoft.com")
.execute(new AsyncCompletionHandler<Response>(){
#Override
public Response onCompleted(Response resp) throws Exception {
promise.complete(resp.getResponseBody().length());
return resp;
}
});
return promise;
}
Second approach less verbose but blocking a thread:
static CompletableFuture<Integer> AccessTheWebAsync(){
try(AsyncHttpClient asyncHttpClient = new AsyncHttpClient()){
Future<Response> f = asyncHttpClient
.prepareGet("https://msdn.microsoft.com")
.execute();
return CompletableFuture.supplyAsync(
() -> return f.join().getResponseBody().length());
}
}

async and await are syntactic sugars. The essence of async and await is state machine. The compiler will transform your async/await code into a state machine.
At the same time, in order for async/await to be really practicable in real projects, we need to have lots of Async I/O library functions already in place. For C#, most original synchronized I/O functions has an alternative Async version. The reason we need these Async functions is because in most cases, your own async/await code will boil down to some library Async method.
The Async version library functions in C# is kind of like the AsynchronousChannel concept in Java. For example, we have AsynchronousFileChannel.read which can either return a Future or execute a callback after the read operation is done. But it’s not exactly the same. All C# Async functions return Tasks (similar to Future but more powerful than Future).
So let’s say Java do support async/await, and we write some code like this:
public static async Future<Byte> readFirstByteAsync(String filePath) {
Path path = Paths.get(filePath);
AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);
ByteBuffer buffer = ByteBuffer.allocate(100_000);
await channel.read(buffer, 0, buffer, this);
return buffer.get(0);
}
Then I would imagine the compiler will transform the original async/await code into something like this:
public static Future<Byte> readFirstByteAsync(String filePath) {
CompletableFuture<Byte> result = new CompletableFuture<Byte>();
AsyncHandler ah = new AsyncHandler(result, filePath);
ah.completed(null, null);
return result;
}
And here is the implementation for AsyncHandler:
class AsyncHandler implements CompletionHandler<Integer, ByteBuffer>
{
CompletableFuture<Byte> future;
int state;
String filePath;
public AsyncHandler(CompletableFuture<Byte> future, String filePath)
{
this.future = future;
this.state = 0;
this.filePath = filePath;
}
#Override
public void completed(Integer arg0, ByteBuffer arg1) {
try {
if (state == 0) {
state = 1;
Path path = Paths.get(filePath);
AsynchronousFileChannel channel = AsynchronousFileChannel.open(path);
ByteBuffer buffer = ByteBuffer.allocate(100_000);
channel.read(buffer, 0, buffer, this);
return;
} else {
Byte ret = arg1.get(0);
future.complete(ret);
}
} catch (Exception e) {
future.completeExceptionally(e);
}
}
#Override
public void failed(Throwable arg0, ByteBuffer arg1) {
future.completeExceptionally(arg0);
}
}

There is no equivalent of C# async/await in Java at the language level. A concept known as Fibers aka cooperative threads aka lightweight threads could be an interesting alternative. You can find Java libraries providing support for fibers.
Java libraries implementing Fibers
JetLang
Kilim
Quasar
You can read this article (from Quasar) for a nice introduction to fibers. It covers what threads are, how fibers can be implemented on the JVM and has some Quasar specific code.

As it was mentioned, there is no direct equivalent, but very close approximation could be created with Java bytecode modifications (for both async/await-like instructions and underlying continuations implementation).
I'm working right now on a project that implements async/await on top of JavaFlow continuation library, please check https://github.com/vsilaev/java-async-await
No Maven mojo is created yet, but you may run examples with supplied Java agent. Here is how async/await code looks like:
public class AsyncAwaitNioFileChannelDemo {
public static void main(final String[] argv) throws Exception {
...
final AsyncAwaitNioFileChannelDemo demo = new AsyncAwaitNioFileChannelDemo();
final CompletionStage<String> result = demo.processFile("./.project");
System.out.println("Returned to caller " + LocalTime.now());
...
}
public #async CompletionStage<String> processFile(final String fileName) throws IOException {
final Path path = Paths.get(new File(fileName).toURI());
try (
final AsyncFileChannel file = new AsyncFileChannel(
path, Collections.singleton(StandardOpenOption.READ), null
);
final FileLock lock = await(file.lockAll(true))
) {
System.out.println("In process, shared lock: " + lock);
final ByteBuffer buffer = ByteBuffer.allocateDirect((int)file.size());
await( file.read(buffer, 0L) );
System.out.println("In process, bytes read: " + buffer);
buffer.rewind();
final String result = processBytes(buffer);
return asyncResult(result);
} catch (final IOException ex) {
ex.printStackTrace(System.out);
throw ex;
}
}
#async is the annotation that flags a method as asynchronously executable, await() is a function that waits on CompletableFuture using continuations and a call to "return asyncResult(someValue)" is what finalizes associated CompletableFuture/Continuation
As with C#, control flow is preserved and exception handling may be done in regular manner (try/catch like in sequentially executed code)

Java itself has no equivalent features, but third-party libraries exist which offer similar functionality, e.g.Kilim.

Java doesn't have direct equivalent of C# language feature called async/await, however there's a different approach to the problem that async/await tries to solve. It's called project Loom, which will provide virtual threads for high-throughput concurrency. It will be available in some future version of OpenJDK.
This approach also solves "colored function problem" that async/await has.
Similar feature can be also found in Golang (goroutines).

First, understand what async/await is. It is a way for a single-threaded GUI application or an efficient server to run multiple "fibers" or "co-routines" or "lightweight threads" on a single thread.
If you are ok with using ordinary threads, then the Java equivalent is ExecutorService.submit and Future.get. This will block until the task completes, and return the result. Meanwhile, other threads can do work.
If you want the benefit of something like fibers, you need support in the container (I mean in the GUI event loop or in the server HTTP request handler), or by writing your own.
For example, Servlet 3.0 offers asynchronous processing. JavaFX offers javafx.concurrent.Task. These don't have the elegance of language features, though. They work through ordinary callbacks.

There isn't anything native to java that lets you do this like async/await keywords, but what you can do if you really want to is use a CountDownLatch. You could then imitate async/await by passing this around (at least in Java7). This is a common practice in Android unit testing where we have to make an async call (usually a runnable posted by a handler), and then await for the result (count down).
Using this however inside your application as opposed to your test is NOT what I am recommending. That would be extremely shoddy as CountDownLatch depends on you effectively counting down the right number of times and in the right places.

I make and released Java async/await library.
https://github.com/stofu1234/kamaitachi
This library don't need compiler extension, and realize stackless IO processing in Java.
async Task<int> AccessTheWebAsync(){
HttpClient client= new HttpClient();
var urlContents= await client.GetStringAsync("http://msdn.microsoft.com");
  return urlContents.Length;
}
   ↓
//LikeWebApplicationTester.java
BlockingQueue<Integer> AccessTheWebAsync() {
HttpClient client = new HttpClient();
return awaiter.await(
() -> client.GetStringAsync("http://msdn.microsoft.com"),
urlContents -> {
return urlContents.length();
});
}
public void doget(){
BlockingQueue<Integer> lengthQueue=AccessTheWebAsync();
awaiter.awaitVoid(()->lengthQueue.take(),
length->{
System.out.println("Length:"+length);
}
);
}

There is an "equivalent" of await developed by EA: https://github.com/electronicarts/ea-async. Refer to the Java example code:
import static com.ea.async.Async.await;
import static java.util.concurrent.CompletableFuture.completedFuture;
public class Store
{
public CompletableFuture<Boolean> buyItem(String itemTypeId, int cost)
{
if(!await(bank.decrement(cost))) {
return completedFuture(false);
}
await(inventory.giveItem(itemTypeId));
return completedFuture(true);
}
}

Java has unfortunately no equivalent of async/await. The closest you can get is probably with ListenableFuture from Guava and listener chaining, but it would be still very cumbersome to write for cases involving multiple asynchronous calls, as the nesting level would very quickly grow.
If you're ok with using a different language on top of JVM, fortunately there is async/await in Scala which is a direct C# async/await equivalent with an almost identical syntax and semantics:
https://github.com/scala/async/
Note that although this functionality needed a pretty advanced compiler support in C#, in Scala it could be added as a library thanks to a very powerful macro system in Scala and therefore can be added even to older versions of Scala like 2.10. Additionally Scala is class-compatible with Java, so you can write the async code in Scala and then call it from Java.
There is also another similar project called Akka Dataflow http://doc.akka.io/docs/akka/2.3-M1/scala/dataflow.html which uses different wording but conceptually is very similar, however implemented using delimited continuations, not macros (so it works with even older Scala versions like 2.9).

If you're just after clean code which simulates the same effect as async/await in java and don't mind blocking the thread it is called on until it is finished, such as in a test, you could use something like this code:
interface Async {
void run(Runnable handler);
}
static void await(Async async) throws InterruptedException {
final CountDownLatch countDownLatch = new CountDownLatch(1);
async.run(new Runnable() {
#Override
public void run() {
countDownLatch.countDown();
}
});
countDownLatch.await(YOUR_TIMEOUT_VALUE_IN_SECONDS, TimeUnit.SECONDS);
}
await(new Async() {
#Override
public void run(final Runnable handler) {
yourAsyncMethod(new CompletionHandler() {
#Override
public void completion() {
handler.run();
}
});
}
});

I have developed a library JAsync to do this.
It is just released today.
It makes the developer's asynchronous programming experience as close as possible to the usual synchronous programming, including code style and debugging.
Here is the example.
#RestController
#RequestMapping("/employees")
public class MyRestController {
#Inject
private EmployeeRepository employeeRepository;
#Inject
private SalaryRepository salaryRepository;
// The standard JAsync async method must be annotated with the Async annotation, and return a Promise object.
#Async()
private Promise<Double> _getEmployeeTotalSalaryByDepartment(String department) {
double money = 0.0;
// A Mono object can be transformed to the Promise object. So we get a Mono object first.
Mono<List<Employee>> empsMono = employeeRepository.findEmployeeByDepartment(department);
// Transformed the Mono object to the Promise object.
Promise<List<Employee>> empsPromise = JAsync.from(empsMono);
// Use await just like es and c# to get the value of the Promise without blocking the current thread.
for (Employee employee : empsPromise.await()) {
// The method findSalaryByEmployee also return a Mono object. We transform it to the Promise just like above. And then await to get the result.
Salary salary = JAsync.from(salaryRepository.findSalaryByEmployee(employee.id)).await();
money += salary.total;
}
// The async method must return a Promise object, so we use just method to wrap the result to a Promise.
return JAsync.just(money);
}
// This is a normal webflux method.
#GetMapping("/{department}/salary")
public Mono<Double> getEmployeeTotalSalaryByDepartment(#PathVariable String department) {
// Use unwrap method to transform the Promise object back to the Mono object.
return _getEmployeeTotalSalaryByDepartment(department).unwrap(Mono.class);
}
}
And in debug mode, you can see all the variable just like the synchronous code.
The other great thing about this project is that it's one of the few projects of its kind that's still active right now. It's just been released, so it has a lot of potential

Related

Calling async methods in a c# dll from delphi

I'm writing a DLL in C# which goal is to communicate with a web platform using REST. It's going to be used in a Delphi XE program. The problem is, I don't really know how to go about exposing my DLL methods to be visible in Delphi. Basically all of them look something like:
public async Task<string> foo(string bar)
{
string result = await client.GetSomethingAndReturnString(bar);
return result;
}
Is it possible to use those methods from the DLL without registering it? Do I need some sort of a "bridge" in c++ between my library and the target program?
All parameters and return values are strings and I've read about marshalling etc. so I think making the conversion work won't be such a hassle, there are many threads about that.
I won't be writing the Delphi side, however I could have input on how my DLL would be implemented, if that is an important factor.
A quick fix is to convert the async method to something synchronous:
public string Foo(string bar)
{
string result = client.GetSomethingAndReturnString(bar).Result;
return result;
}
Retrieving the Result property will wait until the function is done. Unless the task is cancelled or throws an exception. Slightly improved version:
try
{
return new Client().GetSomethingAndReturnString(bar).Result;
}
catch (Exception e)
{
return e.Message;
}
(Though returning the exception message as data is probably not what you want.)
Or you can wait for the task to finish and inspect the result:
Task<string> task = new Client().GetSomethingAndReturnString(bar);
task.Wait();
return task.IsCompleted ? task.Result : "ERROR!";

PowerShell System.Management.Automation.Runspaces vs TAP in C#

I've recently run into a use case where the "Async" suffix recommended by the .NET Task-based Asynchronous Pattern (TAP) conflicts with what's already in existence.
I'm dealing with System.Management.Automation.Runspaces.Runspace during the course of attempting PowerShell remoting to execute cmdlets as part of my app.
Ignoring the questions that arise around whether it's best practice to knock-up a remoting session each time you want to run a cmdlet (for an enterprise scale application this might be a lot) or to create a connection and attempt to maintain it during the app's lifetime (with reconnection logic)...
My application is based on TAP which proliferates from the WebApi2 controller all the way down to the backend, what I'm trying to do is asynchronously open a Runspace connection - but noticed that there's already an OpenAsync method which isn't awaitable and returns void - which is like some weird mash-up between async void (for event handlers), void (non-async) and the Async suffix.
I'm using Stephen Cleary's Nito.AsyncEx nuget package to provide me with a AsyncAutoResetEvent which I can asynchronously await before attempting connection/reconnection).
The question is: should I care about the fact that my code really isn't going to be properly "async" in using either Open or OpenAsync on the Runspace?
If I should care - what's the best practice in this situation? It doesn't look like Microsoft have released updated DLLs which provide awaitable Open methods for the Runspace. Strangely despite MS giving information on how to use these libraries, they've added the caveat on the nuget site:
Versions 6.1.7601.* are unofficial packages for .Net 4.0 and are not
supported by Microsoft.
There also seems to be this DLL-esque package on nuget from Microsoft, aagggghh!
Currently my plan is something akin to this:
public async Task<Result> StartAsync()
{
if (!IsConnected)
{
try
{
await _asyncRunspaceLock.WaitAsync();
if (!IsConnected)
{
var protocol = IsHttpsEnabled ? "https" : "http";
var serverUrl = $"{protocol}://{Fqdn}/OcsPowershell";
var uri = new Uri(serverUrl);
var connectionInfo = new WSManConnectionInfo(uri, ShelUri, PSCredential.Empty)
{
SkipRevocationCheck = true,
};
var runspace = runspaceFactory.CreateRunspace(connectionInfo);
runspace.OpenAsync();
}
}
catch (Exception ex)
{
// TODO: Handle logging the 3rd party exception at the lowest level.
return Result.Fail(ex.Message);
}
finally
{
_asyncRunspaceLock.Set();
}
}
return Result.Ok();
}
It's a work in progress, I guess the same issue crops up around the RunspaceFactory's CreateRunspace static method which isn't async (at least it isn't named with the Async suffix).
Any helpful advice or experience would be greatly appreciated.
Thanks
peteski
From the documentation:
If you're adding a TAP method to a class that already contains that method name with the Async suffix, use the suffix TaskAsync instead. For example, if the class already has a GetAsync method, use the name GetTaskAsync.

Java equivalent of C# Action.BeginInvoke

I have this C# code:
Action action = MyFunction;
action.BeginInvoke(action.EndInvoke, action);
which, from what I can tell, just runs MyFunction asynchronously. Can you do the same thing in Java?
This is how you could run an action in its own thread in Java:
new Thread(new Runnable() {
#Override
public void run() {
aFunctionThatRunsAsynchronously();
}
}).start();
There are other higher-level frameworks available that give you more control on how things are run such as Executors, which can for example be used to schedule events.
Natively, the ExecutorService provides the closest I can think of. Here's how you can use the ExecutorService to run a method async and then get the return value later:
ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
Future<String> future = executor.submit(new Callable<String>() {
return getSomeLongRunningSomethingHere();
});
//... do other stuff here
String rtnValue = future.get(); //get blocks until the original finishes running
System.out.println(rtnValue);
This is somewhat related to Asynchronous Event Dispatch in Java. Basically, you can structure the method you want to run as a class implementing Callable or Runnable. Java doesn't have the ability to refer to a "method group" as a variable or parameter, like C# does, so even event handlers in Java are classes implementing an interface defining the listener.
Try something like this:
Executor scheduler = Executors.newSingleThreadExecutor();
//You'd have to change MyFunction to be a class implementing Callable or Runnable
scheduler.submit(MyFunction);
More reading from the Oracle Java docs:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Executors.html
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ScheduledExecutorService.html

Silverlight 4: REST API call data retrieval layer?

I'm working in .NET 4 and SL 4.
I'm wanting to abstract out the data retrieval portion of my DAL from my silverlight page's code behind.
Ideally into its own DLL as an interface layer between my silverlight application and REST API calls.
My intent is not to use RIA services as I already have an existing DAL that's making use of a DLL that makes REST API calls.
The issue is the asynchronous "WebClient" call back process.
I know that I can utilize the WebClient class to make a REST call and then register the asynchronous handler to simply bind the results from that call to the UI.
But in my case, I want to abstract this out into its own DLL. Basically....making it synchronous.
By definition an asynchronous call has issues here being that it can't immediately and directly return an IEnumerable of some type.
Can anyone point me to a sample/tutorial where something like this is being done?
RIA makes method call to separate DLL for IEnumerable data collection
That method makes REST API call to retrieve data, then returns that IEnumerable to the RIA and is bound to the UI.
Boling it right down to the fundementals what you are actually asking for is to be able to make a synchronous call into an API that performs an asynchronous task but only returns when that asynchronous task is complete. To state it another way you want to re-combine the Begin and End phases of an asynchronous operation back into a single atomic synchronous operation.
The only way to acheive that is to block the thread making the call until the end phase of the asynchronous operation is reached. For a number of reasons this is not a good idea.
If you are serious about using Silverlight you have to swallow its asynchronous nature and work with in that framework rather than attempting to force it back into a synchronous system.
Converting synchronous to asynchronous
Have a read of this blog about converting synchronous code into asynchronous code. Having read that now lets just imagine that your code uses a synchronous method in your new DLL called DownloadYourDataObjects which has this imaginary signature:-
public IEnumerable<YourDataObject> DownloadYourDataObjects(Uri source);
Internally it use WebClient to download a string from a REST base service and converts it to a set of YourDataObject instances. The imaginary synchronous code to display this set of data might be:-
private void btnLoadMyData_Click(object sender, RoutedEventArgs e)
{
try
{
LoadMyData();
}
catch (Exception err)
{
// Oops something bad happened show err.
}
}
private void LoadMyData()
{
DataItemsListBox.ItemsSource = DownloadYourDataObjects(someUri);
}
Since Silverlight WebClient is asynchronous we need to convert this whole chain of code to work in an asynchronous manner.
Using the AsyncOperationService from the blog we first need to convert the DownloadYourDataObjects to return an AsyncOperation instead. It would have a signature like this (see later for an implementation idea):-
public AsyncOperation DownloadYourDataObjects(Uri source, Action<IEnumerable<YourDataObject>> returnResult);
The usage code would then look something like this:-
private void btnLoadMyData_Click(object sender, RoutedEventArgs e)
{
LoadMyData().Run(err =>
{
if (err != null)
{
// Oops something bad happened show err.
}
});
}
private IEnumerable<AsyncOperation> LoadMyData()
{
yield return DownloadYourDataObjects(someUri, result =>
{
DataItemsListBox.ItemsSource = result;
});
}
This may look a litte OTT but in fact it isn't much more code than the original "synchronous" version. In this simple case LoadMyData only had one operation to perform. A more complex version of LoadMyData may have multiple other operations that need to be asynchronous as well. In such a case those operations would just be other yield points in the code, the basic logical structure of LoadMyData would not change much from an original synchronous version.
Here is an example of an implementation of DownloadYourDataObjects that your DLL would supply.
public AsyncOperation DownloadYourDataObjects(Uri source, Action<IEnumerable<YourDataObject>> returnResult)
{
return (completed) =>
{
WebClient client = new WebClient();
client.DownloadStringCompleted += (s, args) =>
{
try
{
returnResult(ConvertStringToYourDataObjects(args.Result));
completed(null);
}
catch (Exception err)
{
completed(err);
}
};
client.DownloadStringAsync(source);
};
}

Pitfalls of (Mis)Using C# Iterators to Implement Coroutines

I am writing refactoring a Silverlight program to consumes a portion of its existing business logic from a WCF service. In doing so, I've run into the restriction in Silverlight 3 that only allows asynchronous calls to WCF services to avoid cases where long-running or non-responsive service calls block the UI thread (SL has an interesting queuing model for invoking WCF services on the UI thread).
As a consequence, writing what once was straightforward, is becoming rapidly more complex (see the code examples at the end of my question).
Ideally, I would use coroutines to simplify the implementation, but sadly, C# does not currently support coroutines as a native language facility. However, C# does have the concept of generators (iterators) using the yield return syntax. My idea is to re-purpose the yield keyword to allow me to build a simple coroutine model for the same logic.
I am reluctant to do this, however, because I am worried that there may be some hidden (technical) pitfalls that I'm not anticipating (given my relative inexperience with Silverlight and WCF). I am also worried that the implementation mechanism may not be clear to future developers and may hinder rather than simplify their efforts to maintain or extend the code in the future. I've seen this question on SO about re-purposing iterators to build state machines: implementing a state machine using the "yield" keyword, and while it's not exactly the same thing I'm doing, it does make me pause.
However, I need to do something to hide the complexity of the service calls and manage the effort and potential risk of defects in this type of change. I am open to other ideas or approaches I can use to solve this problem.
The original non-WCF version of the code looks something like this:
void Button_Clicked( object sender, EventArgs e ) {
using( var bizLogic = new BusinessLogicLayer() ) {
try {
var resultFoo = bizLogic.Foo();
// ... do something with resultFoo and the UI
var resultBar = bizLogic.Bar(resultFoo);
// ... do something with resultBar and the UI
var resultBaz = bizLogic.Baz(resultBar);
// ... do something with resultFoo, resultBar, resultBaz
}
}
}
The re-factored WCF version becomes quite a bit more involved (even without exception handling and pre/post condition testing):
// fields needed to manage distributed/async state
private FooResponse m_ResultFoo;
private BarResponse m_ResultBar;
private BazResponse m_ResultBaz;
private SomeServiceClient m_Service;
void Button_Clicked( object sender, EventArgs e ) {
this.IsEnabled = false; // disable the UI while processing async WECF call chain
m_Service = new SomeServiceClient();
m_Service.FooCompleted += OnFooCompleted;
m_Service.BeginFoo();
}
// called asynchronously by SL when service responds
void OnFooCompleted( FooResponse fr ) {
m_ResultFoo = fr.Response;
// do some UI processing with resultFoo
m_Service.BarCompleted += OnBarCompleted;
m_Service.BeginBar();
}
void OnBarCompleted( BarResponse br ) {
m_ResultBar = br.Response;
// do some processing with resultBar
m_Service.BazCompleted += OnBazCompleted;
m_Service.BeginBaz();
}
void OnBazCompleted( BazResponse bz ) {
m_ResultBaz = bz.Response;
// ... do some processing with Foo/Bar/Baz results
m_Service.Dispose();
}
The above code is obviously a simplification, in that it omits exception handling, nullity checks, and other practices that would be necessary in production code. Nonetheless, I think it demonstrates the rapid increase in complexity that begins to occur with the asynchronous WCF programming model in Silverlight. Re-factoring the original implementation (which didn't use a service layer, but rather had its logic embedded in the SL client) is rapidly looking to be a daunting task. And one that is likely to be quite error prone.
The co-routine version of the code would look something like this (I have not tested this yet):
void Button_Clicked( object sender, EventArgs e ) {
PerformSteps( ButtonClickCoRoutine );
}
private IEnumerable<Action> ButtonClickCoRoutine() {
using( var service = new SomeServiceClient() ) {
FooResponse resultFoo;
BarResponse resultBar;
BazResponse resultBaz;
yield return () => {
service.FooCompleted = r => NextStep( r, out resultFoo );
service.BeginFoo();
};
yield return () => {
// do some UI stuff with resultFoo
service.BarCompleted = r => NextStep( r, out resultBar );
service.BeginBar();
};
yield return () => {
// do some UI stuff with resultBar
service.BazCompleted = r => NextStep( r, out resultBaz );
service.BeginBaz();
};
yield return () => {
// do some processing with resultFoo, resultBar, resultBaz
}
}
}
private void NextStep<T>( T result, out T store ) {
store = result;
PerformSteps(); // continues iterating steps
}
private IEnumerable<Action> m_StepsToPerform;
private void PerformSteps( IEnumerable<Action> steps ) {
m_StepsToPerform = steps;
PerformSteps();
}
private void PerformSteps() {
if( m_StepsToPerform == null )
return; // nothing to do
m_StepsToPerform.MoveNext();
var nextStep = m_StepsToPerform.Current;
if( nextStep == null ) {
m_StepsToPerform.Dispose();
m_StepsToPerform = null;
return; // end of steps
}
nextStep();
}
There are all sorts of things that need to be improved in the above code. But the basic premise is to factor out the continuation pattern (creating an interception point for exception handling and various checks) while allowing the event-based async model of WCF to drive when each step is performed - basically when the last async WCF call completes. While on the surface this looks like more code, it's worth mentioning that PerformSteps() and NextStep() are reusable, only the implementation in ButtonClickCoRoutine() would change with each different implementation site.
I'm not entirely sure I like this model, and I wouldn't be surprised if a simpler way existed to implement it. But I haven't been able to find one on the "interwebs" or MSDN, or anywhere else. Thanks in advance for the help.
You should definitely look at the Concurrency and Coordination Runtime. It uses iterators for exactly this purpose.
On the other hand, you should also look at Parallel Extensions and its approach to continuations. Parallel Extensions is part of .NET 4.0, whereas the CCR requires separate licensing. I would advise you to go with a framework written by people who eat, breathe and sleep this stuff though. It's just too easy to get details wrong on your own.
The Reactive Extensions for .NET provide a much cleaner model for handling this.
They provide extensions which let you write simple delegates against asynchronous events in a much, much cleaner manner. I recommend looking into them, and adapting them to this situation.
I didn't read your whole thing.
They use this strategy in CCR robotics studio, and a number of other projects use this strategy. An alternative is to use LINQ, see e.g. this blog for a description. The Reactive framework (Rx) is kinda built along these lines.
Luca mentions in his PDC talk that perhaps future version of C#/VB may add async primitives to the language.
In the meantime, if you can use F#, it is a winning strategy. Right now what you can do with F# here blows everything else right out of the water.
EDIT
To quote the example from my blog, suppose you have a WCF client that you want to call a couple methods on. The synchronous version might be written as
// a sample client function that runs synchronously
let SumSquares (client : IMyClientContract) =
(box client :?> IClientChannel).Open()
let sq1 = client.Square(3)
let sq2 = client.Square(4)
(box client :?> IClientChannel).Close()
sq1 + sq2
and the corresponding async code would be
// async version of our sample client - does not hold threads
// while calling out to network
let SumSquaresAsync (client : IMyClientContract) =
async { do! (box client :?> IClientChannel).OpenAsync()
let! sq1 = client.SquareAsync(3)
let! sq2 = client.SquareAsync(4)
do! (box client :?> IClientChannel).CloseAsync()
return sq1 + sq2 }
No crazy callbacks, you can use control constructs like if-then-else, while, try-finally, etc, write it almost exactly like you write straight-line code, and everything work, but now it's async. It's very easy to take a given BeginFoo/EndFoo pair of methods and make the corresponding F# async methods for use in this model.
You may also want to consider Jeffrey Richter's AsyncEnumerator which is part of his 'power threading' library. He worked together with the CCR team to develop CCR. The AsyncEnumerator is according to Jeffrey more 'lightweight' than the CCR. Personally I've played about with AsyncEnumerator but not with the CCR.
I haven't used it in anger though - so far I've found the limitations with using enumerators to implement coroutines too painful. Currently learning F# because of amongst other things async workflows (If I remember the name correctly) which look like they're full fledged coroutines or 'continuations' (I forget the correct name or the exact distinctions between the terms).
Anyway, here's some links:
http://www.wintellect.com/PowerThreading.aspx
Channel 9 video on AsyncEnumerator
MSDN Article

Categories

Resources