我最近一直在使用 F#,最近编写了一个带有 C# Web 项目和 F# 类库的小型 MVC 应用程序,后者包含大部分代码。
我想使用更高版本的 MVC 的异步控制器功能,您可以在其中返回Task<ActionResult>
. 我正在使用 F# 异步计算表达式编写我的代码,但我非常恼火,因为我不得不不断地使用Async.AwaitTask
and将 Async<'T> 转换为 Task<'T> StartAsTask
。
由于我当时正在学习计算表达式,所以我认为“必须有一种方法可以将计算表达式与 Tasks 以及 Async 一起使用,以实现更好的 F#/C# 互操作”,所以我试了一下:
type TaskBuilder () =
member this.ReturnFrom task = task
member this.Return value = Task.FromResult value
member this.Bind (task : Task<'a>, continuation: 'a -> Task<'b>) =
task.ContinueWith(fun (t : _ Task) ->
(t.Result |> continuation).Result)
member this.Zero () = Task.FromResult ()
这似乎有效;运行以下代码:
let task = TaskBuilder()
task {
let! data = (new WebClient()).DownloadStringTaskAsync(Uri "http://www.google.com")
printfn "Downloaded from Google: %A" (data.Length)
}
|> ignore
task {
let! data = (new WebClient()).DownloadStringTaskAsync(Uri "http://www.bing.com")
printfn "Downloaded from Bing: %A" (data.Length)
}
|> ignore
printfn "Hello world"
产生结果:
Here
Downloaded from Bing: 39121
Downloaded from Google: 46005
它给出了异步的外观,如果您从计算表达式返回,您最终会得到正确的类型,所以我谨慎地将其标记为成功。
让我怀疑的事情是我找不到其他人尝试这个的任何例子,所以我很感激一些外部观点
- 这行得通吗?
- 这是一个好主意吗?