Grokking F#async vs.System.Threading.Task 让我考虑一下函数 LoopCuultPrime >: 让loadCustomerProjection id= 使用session=store.OpenSession() 让结果= 会话加载(id) 匹配结果 |NotNull->某些结果 |无

Grokking F#async vs.System.Threading.Task 让我考虑一下函数 LoopCuultPrime >: 让loadCustomerProjection id= 使用session=store.OpenSession() 让结果= 会话加载(id) 匹配结果 |NotNull->某些结果 |无,f#,f#-giraffe,F#,F# Giraffe,session.Load是同步的,并返回一个CustomerReadModel session还提供了一种LoadAsync方法,我一直在使用这种方法: 让loadCustomerProjection id= 使用session=store.OpenSession() 设y=async{ 让!x=session.LoadAsync(id)|>Async.task 返回x } 设x=y |>Async.RunSynchronously 将x与 |NotNull->Some x |无 我想了解的是

session.Load
是同步的,并返回一个
CustomerReadModel

session
还提供了一种
LoadAsync
方法,我一直在使用这种方法:

让loadCustomerProjection id=
使用session=store.OpenSession()
设y=async{
让!x=session.LoadAsync(id)|>Async.task
返回x
}
设x=y |>Async.RunSynchronously
将x与
|NotNull->Some x
|无
我想了解的是:

第二个版本有意义吗?因为它们都有相同的签名:
Guid->CustomerReadModel option
,它在非阻塞行为方面是否增加了任何价值

如果使用Giraffe HttpHandler从调用
loadCustomerProjection
,那么使用此签名
Guid->Async
是否更有意义

或者考虑到长颈鹿的环境,最好是有签名
Guid->Task


在我的长颈鹿处理程序中,我想做的至少是通过404模式匹配处理
null
结果-因此在某个点上,我需要有一个
|>Async.waittask
调用。

因为任务和异步之间的主要区别是,当你有一个任务时,它总是热的,而异步是冷的(直到您决定运行它)在后端代码中使用Async是有意义的,然后当Giraffe需要使用它时,将其转换为任务或运行它

在你的例子中,你只是在做一件事。我想如果你有多个异步步骤,你想以某种方式组合,那么完全异步会更有用


参见示例。

如另一个答案中所述,Task和Async之间的主要区别在于任务立即启动,而Async必须显式启动


在上面的简单示例中,返回't,Async'不会有太大区别。我的首选可能是Task。在这种特殊情况下,第一个版本和第二个版本之间没有区别,只是在第二个版本中,您经历了所有困难来调用Async函数,然后立即等待它。但是第二个版本与第一个版本完全相同

至于其他答案中的热注释与冷注释;因为您将对LoadAsync的调用包装在异步计算表达式中,所以它保持冷态(因为异步表达式仅在运行时执行)

let y =
    session.LoadAsync<CustomerReadModel>(id)
    |> Async.AwaitTask
y=
session.LoadAsync(id)
|>异步任务
然后LoadAsync将立即开始执行

如果您希望支持异步操作,那么将整个函数设置为异步确实是有意义的:

let loadCustomerProjection id =
    async {
        use session = store.OpenSession()
  
        let! x =  session.LoadAsync<CustomerReadModel>(id) |> Async.AwaitTask

        match x with
        | NotNull -> return Some x
        | _ -> return None
    }
让loadCustomerProjection id=
异步的{
使用session=store.OpenSession()
让!x=session.LoadAsync(id)|>Async.task
将x与
|NotNull->返回一些x
|->返回无
}
您是使用Task还是Async取决于您。就个人而言,我更喜欢Async,因为它是F#固有的。但在您的情况下,您可能希望坚持使用Async以避免转换