Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>It is kind of a nightmare to get this right. You need to create callbacks to pass into each 'Begin' method that then run the 'continuation' of the method. (And don't forget to ensure all the exception-handling and CompletedSynchronously logic is correct!) When you author this in C# today, your code turns into a hopeless mess of spaghetti, but that's about the only way you can achieve your goal (not have threads blocking on I/O waits).</p> <p>On the other hand, if it's within reason for your situation, <a href="http://fsharp.net" rel="noreferrer">F#</a> makes this very simple and straightforward to author correctly. See <a href="http://channel9.msdn.com/pdc2008/TL11/" rel="noreferrer">this video</a> (namely, 8 minutes starting at 52:20) for a synopsis.</p> <p>EDIT</p> <p>to answer Dan's comment, here is a very rough sketch... I pulled it from an email I wrote in outlook, I doubt it compiles. The exception paths are always gnarly, so be careful (what if ‘cb’ throws?); you may want to find a rock-solid AR/Begin/End implementation in C# somewhere (I dunno where, I’m sure there must be many) and use it as a model, but this shows the gist. The thing is, once you author this once, you have it for all time; BeginRun and EndRun work as the 'begin/end' on any F# async object. We have a suggestion in the F# bug database to expose the Begin/End APM on top of async in a future release of the F# library, so as to make it easier to consume F# async computations from traditional C# code. (And of course we're striving to work better with 'Task's from the parallel task library in .Net 4.0 as well.)</p> <pre><code>type AR&lt;’a&gt;(o,mre,result) = member x.Data = result interface IAsyncResult with member x.AsyncState = o member x.AsyncWaitHandle = mre member x.CompletedSynchronously = false member x.IsCompleted = mre.IsSignalled let BeginRun(a : Async&lt;’a&gt;, cb : AsyncCallback, o : obj) = let mre = new ManualResetEvent(false) let result = ref None let iar = new AR(o,mre,result) :&gt; IAsyncResult let a2 = async { try let! r = a result := Choice2_1(r) with e -&gt; result := Choice2_2(e) mre.Signal() if cb &lt;&gt; null then cb.Invoke(iar) return () } Async.Spawn(a2) iar let EndRun&lt;’a&gt;(iar) = match iar with | :? AR&lt;’a&gt; as ar -&gt; iar.AsyncWaitHandle.WaitOne() match !(ar.Data) with | Choice2_1(r) -&gt; r | Choice2_2(e) -&gt; raise e </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload