运行 f# 工作流中的 c# 异步方法

Running c# async method in f# workflow

我试图让下面的代码在 F# 异步工作流中工作,但我收到错误 "Unexpected symbol '}' in expression"。一般来说,我对 F# 和异步都比较陌生。我在这里错过了什么。

let someFunction (req : HttpRequestMesssage) a b = 

    // code
    async{
        let! readToProvider =
            req.Content.ReadAsMultipartAsync(provider)
            |> Async.AwaitIAsyncResult 

    } |> Async.RunSynchronously

    req.CreateResponse(HttpStatusCode.OK)

你做得对。您收到错误只是因为您使用 let! 表达式结束 async 块。将其更改为 return!do! ... |> Async.Ignore 即可。

F# 中的块(既不是工作流也不是常规代码块)不应以 let.

结尾

当然,如果所有真的在工作流程中做的是一个调用,您根本不需要工作流块(您永远不需要为单个调用编写块)。就这样

req.Content.ReadAsMultipartAsync provider
  |> Async.AwaitIAsyncResult 
  |> Async.Ignore
  |> Async.RunSynchronously
req.CreateResponse HttpStatusCode.OK

或者就此而言,只需使用内置的 Tasks Wait,它的作用与 Async.RunSynchronously:

(req.Content.ReadAsMultipartAsync provider).Wait()

我担心我之前的回答不是你想要的。我提供的只是帮助您解决了编译错误。但关于它的一件事是,它 not 运行 是异步的。 Task.WaitAsync.RunSynchronously 都会阻塞 运行ning 线程,直到操作完成。

如果你真的想 异步的,即不阻塞,你必须把整个方法,或者至少是它的最后一部分,放到 async 块,这样你实际上是在向调用者返回一个 async 操作。所以答案是

let someFunction (req : HttpRequestMesssage) a b = 
  async {
    let! readToProvider = (req.Content.ReadAsMultipartAsync provider) |> Async.AwaitIAsyncResult 
    return req.CreateResponse HttpStatusCode.OK
  }

这个选项returns不是响应,而是Async<Response>。所以现在 caller 可以决定如何 运行 它,阻塞或真正异步。

这样,如果您使用处理异步请求的网络服务器,那么您可以简单地将此函数连接到端点(可能在点将 Async 转换为 Task连接,因为大多数 .net 异步 Web 服务器都是从 C# 角度编写的)并且它将 运行 异步而不阻塞线程。或者,如果您从另一个异步操作调用它,您可以执行 do! someFunction ... 并且它会 运行 异步。但如果调用者不关心,只想同步 运行,它可以做 someFunction ... |> Async.RunSynchronously。所以你在那里可以获得更大的灵活性。如果这是更常见的用例,您始终可以定义 let someFunctionSync ... = someFunction ... |> Async.RunSynchronously

除非你真的想强制阻止,否则我建议你这样做。