问题
I'm trying to consume a C# library in F#. The library makes heavy use of async/await. I want to use within an async { ... }
workflow in F#.
I see we can Async.AwaitTask
on async C# methods returning Task<T>
, but what about those returning plain Task
?
Perhaps, is there a helper to convert these to Async<unit>
or to convert Task
to Task<unit>
so it will work with Async.AwaitTask
?
回答1:
You can use ContinueWith:
let awaitTask (t: Task) = t.ContinueWith (fun t -> ()) |> Async.AwaitTask
Or AwaitIAsyncResult with infinite timeout:
let awaitTask (t: Task) = t |> Async.AwaitIAsyncResult |> Async.Ignore
回答2:
Update:
The FSharp.Core library for F# 4.0 now includes an Async.AwaitTask
overload that accepts a plain Task
. If you're using F# 4.0 then you should use this core function instead of the code below.
Original answer:
If your task could throw an exception then you probably also want to check for this. e.g.
let awaitTask (task : Task) =
async {
do! task |> Async.AwaitIAsyncResult |> Async.Ignore
if task.IsFaulted then raise task.Exception
return ()
}
回答3:
Update:
The FSharp.Core library for F# 4.0 now includes an Async.AwaitTask overload that accepts a plain Task. If you're using F# 4.0 then you should use this core function instead of the code below.
Original answer:
I really liked Ashley's suggestion using function composition. Additionally, you can extend the Async module like this:
module Async =
let AwaitTaskVoid : (Task -> Async<unit>) =
Async.AwaitIAsyncResult >> Async.Ignore
Then it appears in Intellisense along with Async.AwaitTask. It can be used like this:
do! Task.Delay delay |> Async.AwaitTaskVoid
Any suggestions for a better name?
回答4:
To properly propagate both exceptions and cancellation properly, I think you need something like this (partially based on deleted answer by Tomáš Petříček):
module Async =
let AwaitVoidTask (task : Task) : Async<unit> =
Async.FromContinuations(fun (cont, econt, ccont) ->
task.ContinueWith(fun task ->
if task.IsFaulted then econt task.Exception
elif task.IsCanceled then ccont (OperationCanceledException())
else cont ()) |> ignore)
来源:https://stackoverflow.com/questions/8022909/how-to-async-awaittask-on-plain-task-not-taskt