Ðаn*_*Ðаn 1 f# asynchronous webclient
如何使用F#对异步操作类的内置支持,暴露基于事件的异步模式,如WebClient类?
let Download(url : Uri) =
let client = new WebClient()
let html = client.DownloadString(url)
html
Run Code Online (Sandbox Code Playgroud)
当我尝试将其更改为使用"let!"时 在异步块中(如Soma最近的帖子中所述)
let Download(url : Uri) =
async {
let client = new WebClient()
let! html = client.DownloadStringAsync(url)
return html }
Run Code Online (Sandbox Code Playgroud)
我收到一条错误消息:
类型约束不匹配.类型单位与Async <'a>类型不兼容类型'unit'与'Async <'a>类型不兼容
编辑:我真的在询问使用*Async()方法的一般问题,WebClient只是一个简单的例子.微软说 "......你应该尽可能使用基于事件的异步模式[而不是BeginFoo()/ EndFoo()]来暴露异步功能......"所以我认为应该有一种简单的方法来消耗任意*来自F#的Async()方法.
该WebClient.DownloadStringAsync方法是.NET框架的一部分.它会引发一个事件来指示它的进度,它的返回类型是unit,所以你不想使用它,并且将它包装在一个async对象中是没有优势的.
F#PowerPack定义了一种扩展方法,val webclient.AsyncDownloadString : uri -> Async{string}:
let Download(url : Uri) =
async {
let client = new WebClient()
client.Encoding <- Encoding.GetEncoding("utf-8")
let! html = client.AsyncDownloadString(url)
return html }
Run Code Online (Sandbox Code Playgroud)
不幸的是,名称的选择与现有的webclient方法发生冲突,这可以理解地引起混淆.但是,我相信所有的F#异步扩展都以Async*.
[编辑添加以回应评论:]
通常,.NET使用BeginFoo/EndFoo模式进行并发.如果类型是正确的,您可以使用Async.BuildPrimitive beginMethod endMethod,这将返回该方法的Async包装器.
有时对象不使用此模式,如WebClient,您实际上必须使用Async.AwaitEvent等待事件被触发,或者编写自己的循环以反复检查是否设置了bool.这是一篇关于将事件转换为Async对象的好文章.
值得一提的是,如果安装了F#,您还应该拥有源代码,以便了解F#团队如何实现其异步扩展.在我的机器上,相关文件位于:
C:\Program Files\FSharp-1.9.6.16\source\fsppack\FSharp.PowerPack\AsyncOperations.fs
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1336 次 |
| 最近记录: |