F# 如何在普通任务(而不是任务<;T>;)上异步.AwaitTask?
我正试图在F中使用一个C库。该库大量使用async/await。我想在F#中的F# 如何在普通任务(而不是任务<;T>;)上异步.AwaitTask?,f#,async-await,F#,Async Await,我正试图在F中使用一个C库。该库大量使用async/await。我想在F#中的异步{…}工作流中使用 我知道我们可以对返回Task的异步C方法执行Async.waittask,但是那些返回普通Task的方法呢 也许,是否有帮助程序将这些转换为Async,或者将Task转换为Task,这样它将与Async.waittask一起工作?您可以使用ContinueWith: let awaitTask (t: Task) = t.ContinueWith (fun t -> ()) |> A
异步{…}
工作流中使用
我知道我们可以对返回Task
的异步C方法执行Async.waittask
,但是那些返回普通Task
的方法呢
也许,是否有帮助程序将这些转换为
Async
,或者将Task
转换为Task
,这样它将与Async.waittask
一起工作?您可以使用ContinueWith:
let awaitTask (t: Task) = t.ContinueWith (fun t -> ()) |> Async.AwaitTask
或等待无限超时的同步结果:
let awaitTask (t: Task) = t |> Async.AwaitIAsyncResult |> Async.Ignore
更新: F#4.0的FSharp.Core库现在包含一个接受普通任务的Async.AwaitTask重载。如果您使用的是F#4.0,那么您应该使用这个核心函数,而不是下面的代码 原始答案: 我真的很喜欢Ashley使用函数组合的建议。此外,您可以像这样扩展异步模块:
module Async =
let AwaitTaskVoid : (Task -> Async<unit>) =
Async.AwaitIAsyncResult >> Async.Ignore
do! Task.Delay delay |> Async.AwaitTaskVoid
有没有更好的名字的建议?更新: F#4.0的FSharp.Core库现在包括一个
Async.AwaitTask
重载,它接受一个普通的任务。如果您使用的是F#4.0,那么您应该使用这个核心函数,而不是下面的代码
原始答案:
如果您的任务可能引发异常,那么您可能还需要检查此异常。e、 g
let awaitTask (task : Task) =
async {
do! task |> Async.AwaitIAsyncResult |> Async.Ignore
if task.IsFaulted then raise task.Exception
return ()
}
为了正确地传播异常和取消,我认为您需要这样的东西(部分基于TomášPetříček删除的答案):
模块异步=
让任务(任务:任务):异步=
Async.FromContinuations(乐趣(cont,econt,ccont)->
任务。继续(有趣的任务->
如果task.IsFaulted,则econt task.Exception
elif task.iscancelled然后ccont(OperationCanceledException())
else cont())|>忽略)
啊,我明白了。当然,任务毕竟是一个iSyncResult。缩短为let awaitask=Async.awaiiasyncresult>>Async.Ignore
非常感谢!ContinueWith不是惯用的F#,而且它很危险,因为它可能引发TaskCanceledException引发task。Exception
只会引发AggregateException;最好访问它的InnerExceptions
集合,并引发第一个集合(只要集合不是空的)
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)