我正在尝试将以下代码用于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)
答案 0 :(得分:6)
我担心我之前的回答并不是你想要的。我提供的只是让你完成编译错误。但有一点是,它确实不异步运行。 Task.Wait
和Async.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
阻止而导致错误。将其更改为let
或req.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