13.07.2015 Views

C# in Depth

C# in Depth

C# in Depth

SHOW MORE
SHOW LESS
  • No tags were found...

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

180 CHAPTER 6 Implement<strong>in</strong>g iterators the easy wayvoid AfterGetRates(IAsyncResult result){IAsyncResult hold<strong>in</strong>gsAsync = (IAsyncResult)result.AsyncState;StockRates rates = StockService.EndGetRates(result);Hold<strong>in</strong>gs hold<strong>in</strong>gs = DbService.EndGetStockHold<strong>in</strong>gs(hold<strong>in</strong>gsAsync);}OnRequestComplete(ProcessStocks(stocks, rates));This is much harder to read and understand—and that’s only a simple version! Thecoord<strong>in</strong>ation of the two parallel calls is only achievable <strong>in</strong> a simple way because wedon’t need to pass any other state around, and even so it’s not ideal. (It will still blocka thread wait<strong>in</strong>g for the database call to complete if the second web service call completesfirst.) It’s far from obvious what’s go<strong>in</strong>g on, because the code is jump<strong>in</strong>g arounddifferent methods so much.By now you may well be ask<strong>in</strong>g yourself where iterators come <strong>in</strong>to the picture. Well,the iterator blocks provided by <strong>C#</strong> 2 effectively allow you to “pause” current executionat certa<strong>in</strong> po<strong>in</strong>ts of the flow through the block, and then come back to the same place,with the same state. The clever folks design<strong>in</strong>g the CCR realized that that’s exactlywhat’s needed for someth<strong>in</strong>g called a cont<strong>in</strong>uation-pass<strong>in</strong>g style of cod<strong>in</strong>g. We need totell the system that there are certa<strong>in</strong> operations we need to perform—<strong>in</strong>clud<strong>in</strong>g start<strong>in</strong>gother operations asynchronously—but that we’re then happy to wait until theasynchronous operations have f<strong>in</strong>ished before we cont<strong>in</strong>ue. We do this by provid<strong>in</strong>gthe CCR with an implementation of IEnumerator (where ITask is an <strong>in</strong>terfacedef<strong>in</strong>ed by the CCR). Here’s pseudo-code for our request handl<strong>in</strong>g <strong>in</strong> this style:IEnumerator ComputeTotalStockValue(str<strong>in</strong>g user, str<strong>in</strong>g pass){Token token = null;}yield return Ccr.ReceiveTask(AuthService.CcrCheck(user, pass)delegate(Token t){ token = t; });Hold<strong>in</strong>gs stocks = null;StockRates rates = null;yield return Ccr.MultipleReceiveTask(DbService.CcrGetStockHold<strong>in</strong>gs(token),StockService.CcrGetRates(token),delegate(Stocks s, StockRates sr){ stocks = s; rates = sr; });OnRequestComplete(ProcessStocks(stocks, rates));Confused? I certa<strong>in</strong>ly was when I first saw it—but now I’m somewhat <strong>in</strong> awe of how neatit is. The CCR will call <strong>in</strong>to our code (with a call to MoveNext on the iterator), and we’llexecute until and <strong>in</strong>clud<strong>in</strong>g the first yield return statement. The CcrCheck methodwith<strong>in</strong> AuthService would kick off an asynchronous request, and the CCR would waitLicensed to Rhona Hadida

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!