找不到简单的异步等待方法

use*_*676 3 f#

假设我需要执行一些异步操作,并且我现在需要结果。如果我使用 C#,我会这样做:

var contents = await File.ReadAllLinesAsync(...);
Run Code Online (Sandbox Code Playgroud)

这里重要的一点是它是非阻塞操作。

我知道Async.RunSynchronously,但文档表明它是阻塞Task.Result操作,这意味着它并不比C#更好。

如果我需要在 F# 中执行相同操作,如何在不阻塞的情况下读取文件内容?

Tom*_*cek 5

正如 Bartosz 的回答中所解释的,在 F# 中的方法await内部使用相当于在计算表达式块内部async使用。let!如果您正在处理 .NET 任务,则可以使用task { ... }; 如果您正在处理 F# 异步计算,那么您可以使用async { ... }.

要使用,async { .. }您还可以使用以下方法将任务转换为异步计算Async.AwaitTask

let run () = async {
  let! contents = File.ReadAllLinesAsync "/path" |> Async.AwaitTask
  return contents
}
Run Code Online (Sandbox Code Playgroud)

如何实际运行该run ()功能?首先,没有办法在不阻塞的情况下运行计算并等待结果。如果您需要同步代码块中的结果,则只需阻塞即可。这与任务相同 - 您可以让它们在后台运行和完成,在另一个非阻塞任务中使用它们或阻塞并等待。

如果您不在另一个async { .. }街区内,您可以做的两件事是:

// Run the task, do something with the result and
// start the whole operation without blocking 
async { 
  let! result = run ()
  printf "%s" result }
|> Async.Start

// Block and wait for the result using RunSynchronously
let result = 
  run ()
  |> Async.RunSynchronously
Run Code Online (Sandbox Code Playgroud)

  • 在 F# 中,情况完全相同 - 您编写的代码在 `async { .. }` 块内都是同步的(相当于将方法标记为 `async`),并且在这些块内,您可以使用 `let 调用其他异步代码!`(相当于“await”)。有关更多详细信息,这可能会有所帮助:http://tomasp.net/blog/csharp-fsharp-async-intro.aspx/ (3认同)
  • 或者你的意思是使用“await”?如果是这样,那么您只能在标记为“async”的方法中执行此操作,这反过来又会使该方法返回“Task”。因此,这与将 F# 代码包装在“async { ... }”中完全相同,这也会使其返回“Async”,即延迟计算。 (2认同)