F# asynchrony and Task -> Task<unit> conversion
Quite a number of useful library XxxXxxAsync
methods return just plain Task
objects, when what it means is that the synchronous operation has a void type. This causes a bit of a snag when calling from F#, as it expects the subclass Task<T>
in the natural way of things. And there are no good hits on the topic of Task
-> Task<unit>
conversion -- so this is a compendium of the techniques that do the job.
So we can treat the Task
as an IAsyncResult
and use
to translate via an Async<Boolean>
to Async<unit>
; or convert the Task
to a Task<unit>
via a continuation and AwaitTask
that
The latter, based on the helper awaitPlainTask
method at theburningmonk.com, separating out the bit before you pipe it into Async.AwaitTask
(then
by composition); this Ignore
function is analogous to Async.Ignore
, and can be used in that sort of role for all Task
and Task<T>
inputs. For example, in conjunction with the fsharpx Task
computation expression, where it fills in a painful gap when faced with plain Task
s.
2 comments :
Or extend async {} so that you can directly use both kinds of Task without Async.AwaitTask at all..
[]
module Async =
let inline AwaitUnitTask (task: Task) =
// rethrow exception from preceding task if it fauled
let continuation (t : Task) : unit =
match t.IsFaulted with
| true -> raise t.Exception
| _ -> ()
task.ContinueWith continuation |> Async.AwaitTask
type Microsoft.FSharp.Control.AsyncBuilder with
member x.Bind (t : Task<'T>, f : 'T -> Async<'R>) : Async<'R> = x.Bind (Async.AwaitTask t, f)
member x.Bind (t : Task, f : unit -> Async) : Async = x.Bind (Async.AwaitUnitTask t, f)
Yes does the whole job of making them part of the Async infrastructure -- and there's a similar transformation to extend the FSharpx.Task module, which is where I hit the problem of needing to make this conversion. In either case, it's all variations on the same core theme.
Exactly where to draw boundaries of small functions composed, or larger monolithic functions is one of these matters of style (if you only ever call a function in a composition, do you keep it as a separate concern or not?). For a blog post I'd rather give the smallest nuggets of functionality and let people weld them together as they see fit for their particular needs.
Post a Comment