我有一个这样的C# API:
Task<T> Foo(serverUri)
假设我有 4 个可能的服务器 URI。我想实现一个将返回 DiscUnionBar 类型的函数:
type DiscUnionBar of T =
Safe of T | Weak of T | ConnectionError
实现将具有以下要求:
使用 3 个- 不同的服务器 Uri 对 Foo(( 进行 3(最多(个并发调用。
- 选择两个最快的成功响应。如果它们给出相同的结果 T1 和 T2(即 T1==T2(,请停止执行并发请求并忽略/取消正在进行的请求并返回 T 的安全。 如果 T1!=T2,请继续执行更多请求(或查看响应(,直到找到两个相等的响应。
- 如果任何请求失败(抛出 ServerException(,请尝试使用以前未请求过的 serverUri。
- 如果对所有 4 台服务器的所有请求都失败,则返回连接错误。
- 如果只有 1 个请求成功,则返回 Weak of T。
考虑到我不能使用 F# 的异步并且必须坚持使用 C# 的任务用法,这很容易做到吗?我对这个有点迷茫。
除非有原因不能在代码中的任何位置使用Async
,并且唯一的限制是Foo
必须返回Task
,否则将调用Foo
产生的Task
转换为具有Async.AwaitTask
的Async
应该没有问题。
这样,可以使用 F# 的异步计算表达式生成逻辑,就像Foo
返回Async
let simpleComputation serverUri = async {
let! fooResult = Foo(serverUri) |> Async.AwaitTask
(* here you can work with the T returned by Foo's task *)
}
我对FSharp.Control.FusionTasks
库也有很好的经验,它允许您直接在异步计算表达式中使用Task
,而无需显式调用AwaitTask
,并且通常有助于异步/任务互操作。尽管有些人可能不喜欢它试图隐藏任务。