F# 如何使此函数正确地异步?
我试图让F#async工作,但我就是不知道我做错了什么。下面是我运行的一些同步代码:F# 如何使此函数正确地异步?,f#,F#,我试图让F#async工作,但我就是不知道我做错了什么。下面是我运行的一些同步代码: open System.Net open System.Runtime.Serialization open System.Threading.Tasks [<DataContract>] type Person = { [<field: DataMember(Name = "name")>] Name : string [<field: DataMemb
open System.Net
open System.Runtime.Serialization
open System.Threading.Tasks
[<DataContract>]
type Person = {
[<field: DataMember(Name = "name")>]
Name : string
[<field: DataMember(Name = "phone")>]
Phone : int
}
let url = "http://localhost:5000/app/plugins/anon/CCure"
let js = Json.DataContractJsonSerializer(typeof<Person>)
let main x =
let client = new WebClient()
let url = url + "/" + x
let reader = client.OpenRead(url)
let person = js.ReadObject(reader) :?> Person
printfn "Name: %s, Phone number: %d" person.Name person.Phone
printfn "starting x"
let x = Task.Factory.StartNew(fun () -> main "x")
printfn "starting y"
let y = Task.Factory.StartNew(fun () -> main "y")
Task.WaitAll(x, y)
开放系统.Net
open System.Runtime.Serialization
开放系统.Threading.Tasks
[]
类型人={
[]
名称:string
[]
电话:int
}
让url=”http://localhost:5000/app/plugins/anon/CCure"
让js=Json.DataContractJsonSerializer(typeof)
让main x=
let client=new WebClient()
设url=url+“/”+x
让reader=client.OpenRead(url)
让person=js.ReadObject(reader):?>person
printfn“姓名:%s,电话号码:%d”person.Name person.Phone
打印fn“开始x”
设x=Task.Factory.StartNew(fun()->main“x”)
打印fn“开始y”
让y=Task.Factory.StartNew(fun()->main“y”)
Task.WaitAll(x,y)
我认为异步运行它会起作用,但它不能:
open System.Net
open System.Runtime.Serialization
open System.Threading.Tasks
[<DataContract>]
type Person = {
[<field: DataMember(Name = "name")>]
Name : string
[<field: DataMember(Name = "phone")>]
Phone : int
}
let url = "http://localhost:5000/app/plugins/anon/CCure"
let js = Json.DataContractJsonSerializer(typeof<Person>)
let main x = async {
let client = new WebClient()
let url = url + "/" + x
let! reader = client.OpenReadAsync(url)
let person = js.ReadObject(reader) :?> Person
printfn "Name: %s, Phone number: %d" person.Name person.Phone }
printfn "starting x"
let x = Task.Factory.StartNew(fun () -> main "x")
printfn "starting y"
let y = Task.Factory.StartNew(fun () -> main "y")
Task.WaitAll(x, y)
开放系统.Net
open System.Runtime.Serialization
开放系统.Threading.Tasks
[]
类型人={
[]
名称:string
[]
电话:int
}
让url=”http://localhost:5000/app/plugins/anon/CCure"
让js=Json.DataContractJsonSerializer(typeof)
让main x=async{
let client=new WebClient()
设url=url+“/”+x
let!reader=client.OpenReadAsync(url)
让person=js.ReadObject(reader):?>person
printfn“姓名:%s,电话号码:%d”person.Name person.Phone}
打印fn“开始x”
设x=Task.Factory.StartNew(fun()->main“x”)
打印fn“开始y”
让y=Task.Factory.StartNew(fun()->main“y”)
Task.WaitAll(x,y)
$fsharpc-r System.Runtime.foo.fs&&./foo.exe F#
F#3.1(开源版)编译器在
Apache 2.0开放源代码许可证
/home/frew/code/foo.fs(19,18):错误FS0001:此表达式无效
期望有类型
Async
OpenReadAsync
是.NET BCL的一部分,因此设计时没有考虑F#Async。您会注意到它返回的是unit
,而不是Async
,因此它不能与let!一起工作
API设计用于事件(即,您必须连接客户端.OpenReadCompleted
)
你有几个选择
FSharp.Core
中有一些很好的助手方法可以提供帮助
您需要将API转换为更友好的API(请参见
Async.AwaitEvent
)AsyncDownloadString
,这是一种WebClient的扩展方法,可以在Microsoft.FSharp.Control.WebExtensions
中找到。这更容易,所以我在下面做了,虽然这确实意味着将整个流作为字符串保存在内存中,所以如果您有大量Json,这可能不是最好的主意open System.Net
open System.Runtime.Serialization
open System.Threading.Tasks
open Microsoft.FSharp.Control.WebExtensions
open System.Runtime.Serialization.Json
[<DataContract>]
type Person = {
[<field: DataMember(Name = "name")>]
Name : string
[<field: DataMember(Name = "phone")>]
Phone : int
}
let url = "http://localhost:5000/app/plugins/anon/CCure"
let js = Json.DataContractJsonSerializer(typeof<Person>)
let main x = async {
printfn "Starting %s" x
let client = new WebClient()
let url = url + "/" + x
let! json = client.AsyncDownloadString(System.Uri(url))
let bytes = System.Text.Encoding.UTF8.GetBytes(json)
let st = new System.IO.MemoryStream(bytes)
let person = js.ReadObject(st) :?> Person
printfn "Name: %s, Phone number: %d" person.Name person.Phone }
let x = main "x"
let y = main "y"
[x;y] |> Async.Parallel |> Async.RunSynchronously |> ignore<unit[]>
开放系统.Net
open System.Runtime.Serialization
开放系统.Threading.Tasks
打开Microsoft.FSharp.Control.WebExtensions
open System.Runtime.Serialization.Json
[]
类型人={
[]
名称:string
[]
电话:int
}
让url=”http://localhost:5000/app/plugins/anon/CCure"
让js=Json.DataContractJsonSerializer(typeof)
让main x=async{
打印fn“开始%s”x
let client=new WebClient()
设url=url+“/”+x
让!json=client.AsyncDownloadString(System.Uri(url))
让bytes=System.Text.Encoding.UTF8.GetBytes(json)
设st=新系统.IO.MemoryStream(字节)
让person=js.ReadObject(st):?>person
printfn“姓名:%s,电话号码:%d”person.Name person.Phone}
设x=主“x”
设y=main“y”
[x;y]|>异步.Parallel |>异步.RunSynchronously |>忽略
我猜是主异步块中的printfn
语句。也许添加person
作为回报会有所帮助。这里似乎有些不正确。。。我从中得到这个异常:System.IO.FileNotFoundException:找不到文件“/home/frew/code/fsharp/{“name”:“john”,“phone”:12312}”。