在f#工作流中运行c#async方法

时间:2015-05-10 20:39:06

标签: f# async-await c#-to-f#

我正在尝试将以下代码用于F#异步工作流程,但我在表达式中收到错误“Unexpected symbol'}'”。我对F#和async都很新。我在这里错过了什么。

let someFunction (req : HttpRequestMesssage) a b = 

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

    } |> Async.RunSynchronously

    req.CreateResponse(HttpStatusCode.OK)

2 个答案:

答案 0 :(得分:6)

我担心我之前的回答并不是你想要的。我提供的只是让你完成编译错误。但有一点是,它确实异步运行。 Task.WaitAsync.RunSynchronously将阻止正在运行的线程,直到操作完成。

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

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

选项不返回响应,而是返回Async<Response>。所以现在调用者可以决定如何运行它,阻塞或真正异步。

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

除非你真的想要强制执行阻止,否则我建议采用这种方式。

答案 1 :(得分:5)

你做得对。您只是因为使用return!表达式结束do! ... |> Async.Ignore阻止而导致错误。将其更改为letreq.Content.ReadAsMultipartAsync provider |> Async.AwaitIAsyncResult |> Async.Ignore |> Async.RunSynchronously req.CreateResponse HttpStatusCode.OK ,您就会变得更好。

F#中的块(工作流和常规代码块)不应以(req.Content.ReadAsMultipartAsync provider).Wait() 结尾。

当然,如果所有 工作流程块(你真的不需要为一次调用编写一个块)。只是做

a

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

MemberProfile