【问题标题】:F# await Task and use its resultF# await 任务并使用其结果
【发布时间】:2020-06-17 07:43:47
【问题描述】:

我对 F# 有点陌生,我正在尝试在 F# 模块中使用一些 C# 类。

let getApps (context: MyContext) =
    context.Provider.GetService<AppRepository>().GetActiveAsync().Result
    |> List.ofSeq
    |> List.map printName
    |> ignore

我的 C# 开发人员尖叫:.Result 很糟糕 ????。所以我的问题是,如何将这段代码重构为更优雅的方式,并利用 F# 中适当的异步编程。

我一直在尝试使用不同的变体:

|> Async.AwaitTask
|> Async.RunSynchronously

但它看起来很丑而且不短,并不是说我不确定它是否有效地利用了处理器时间。

【问题讨论】:

  • 这不就是let! getApps (context: MyContext) = context.Provider.GetService&lt;AppRepository&gt;()吗? (与with open FSharp.Control.Tasks) - 相关:docs.microsoft.com/en-us/dotnet/fsharp/tutorials/…
  • @Andrei context.Provider.GetService() 是什么类型? GetActiveAsync 是什么类型的?
  • @KoenigLear GetActiveAsync 的类型为Task&lt;List&lt;App&gt;&gt;GetService&lt;AppRepository&gt;() 的类型为 AppRepository。这些都是 C# 类

标签: .net .net-core f#


【解决方案1】:

要记住的一点是Async.RunSynchronously 与访问Result 基本相同。这两个操作都会阻塞当前线程,等到后台操作完成后再给你结果。

这意味着如果您需要使用RunSynchronously 等待结果,那么使用async { .. } 是没有意义的。 (除了RunSynchronously 有一个非常长且丑陋的名字,它明确而明确地告诉你这是怎么回事!)

如果您可以构建您的代码以便您无需等待,那么值得更改 getApps 以便它异步返回结果:

let getApps (context: MyContext) = async {        
  let! repos = 
    context.Provider.GetService<AppRepository>().GetActiveAsync()
    |> Async.AwaitTask
  return repos |> List.map printName }

然后您可以从另一个 async { .. } 块调用它,并最终使用 Async.Start 在后台启动计算。但是,如果您使用Async.RunSynchronously,那么这样做是没有意义的。

【讨论】:

  • 有点失望 F# 没有提供更短的语法来处理任务。让我很难证明在企业项目中使用它是合理的,并且一切都是异步的。无论如何感谢您的回答!
  • @Andrei TaskBuilder.fs 在这方面对我很有帮助 (nuget.org/packages/TaskBuilder.fs)
【解决方案2】:

下面应该可以解决问题:

let getApps (context: MyContext) =
    async{
       let! result = context.Provider.GetService<AppRepository>().GetActiveAsync() 
                     |> Async.AwaitTask

       result
       |> Seq.iter printName
    }

getApps ctx
|> Async.RunSynchronously

这样您在等待 GetActive 完成时不会阻塞线程。附带说明一下,如果您正在执行某些操作,您可以使用 Seq.iter 而不是 Seq.map 并且您不需要转换为列表。您可以使用 seq。

【讨论】:

  • 感谢您的回答!我在这里遇到了一些麻烦prnt.sc/t110op。你能指出我的错误吗?
  • @Andrei 缩进问题!只需将 getApps 下面的所有内容都推到一个选项卡上。我编辑了上面的示例以突出显示它。
  • 好棒!感谢你的帮助! VSCode 工具不是很好。你对在 Mac 上使用什么有什么建议吗?
  • @Andrei 缩进错误很痛苦,无论编辑器如何,即使在 Windows 中的 VS 中也是如此。你习惯了它们,可以更容易地发现它们。我也有一台 Mac 和带有 Ionide 扩展的 VSCode 可能是最好的。你可以试试 Visual Studio for Mac,但它有点慢。
  • 是的,试过了。不喜欢它,会坚持使用 VSCode。如果我做全F#也许我会没事,但我的大部分东西都是C#,而F#只是一个小项目,调用F#方法的C#类仍然说,方法不存在叹息。我走的时候一切都会弄清楚的。再次感谢您!
猜你喜欢
  • 1970-01-01
  • 2020-08-15
  • 2020-02-13
  • 2023-03-14
  • 1970-01-01
  • 2021-09-09
  • 1970-01-01
  • 2017-03-12
  • 1970-01-01
相关资源
最近更新 更多