5

我最近一直在使用 F#,最近编写了一个带有 C# Web 项目和 F# 类库的小型 MVC 应用程序,后者包含大部分代码。

我想使用更高版本的 MVC 的异步控制器功能,您可以在其中返回Task<ActionResult>. 我正在使用 F# 异步计算表达式编写我的代码,但我非常恼火,因为我不得不不断地使用Async.AwaitTaskand将 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

它给出了异步的外观,如果您从计算表达式返回,您最终会得到正确的类型,所以我谨慎地将其标记为成功。

让我怀疑的事情是我找不到其他人尝试这个的任何例子,所以我很感激一些外部观点

  1. 这行得通吗?
  2. 这是一个好主意吗?
4

0 回答 0