我正在尝试在F#中使用异步工作流来获取多个Web请求.
但是,我的一些请求偶尔会返回错误(例如http 500),我不知道如何处理这个问题.看起来我的F#程序在调试器中运行时陷入无限循环.
我可能错过了一些东西,因为我看到的例子没有开箱即用.我找到的第一件事就是帮助了这段代码:
type System.Net.WebRequest with
member req.GetResponseAsync() =
Async.BuildPrimitive(req.BeginGetResponse, req.EndGetResponse)
Run Code Online (Sandbox Code Playgroud)
然后我有一些代码来获取请求,这是我见过的例子中非常标准的:
let async_value = async {
let req = WebRequest.Create(url)
let! rsp = req.GetResponseAsync()
return (rsp :?> HttpWebResponse).StatusCode
}
Run Code Online (Sandbox Code Playgroud)
然后我试着得到结果:
let status = Async.RunSynchronously(async_value)
Run Code Online (Sandbox Code Playgroud)
但是当我在调试器中运行我的程序时,它会req.EndGetResponse因为服务器返回内部服务器错误500 而中断.如果我继续执行,它会进入一个时髦的循环,中断req.EndGetResponse(有时连续几次)和let status = Async.RunSynchronously(async_value) .
如何解决异常问题以便获取状态代码?另外,我需要上面做的类型吗?或者我错过了F#/ VS 2010 Beta 1的一些库/ dll,其中这已经是其中的一部分了?
我实际上使用Async.RunSynchronously(Async.Parallel(my_array_of_async_values))并行运行多个请求,尽管我不认为这与我遇到的异常问题有关.
事实上我遇到的例子只是使用Async.Run而不是Async.RunSynchronously可能是一个指标,我错过了一些东西...... = /
它现在称为“AsyncGetResponse”(不再是“GetResponseAsync”)。并且“Run”被重命名为“RunSynchronously”。因此,我认为您在这里没有遗漏任何实质性内容,只是最新版本中的名称更改。
关于“Tools\Options\Debugging\General\Enable Just My Code”和“Debug\Exceptions”的调试器设置是什么(例如设置为在抛出或不抛出任何第一次 CLR 异常时中断)?我不清楚你的问题是否涉及程序行为,或 VS 工具行为(听起来像后者)。F# Beta1 中的断点/调试“位置”存在一些错误,特别是在异步工作流程方面,这意味着即使程序正确执行,您在调试器中看到的行为也可能看起来有点奇怪,这一事实进一步令人困惑。 。
您使用的是VS2008 CTP还是VS2010 Beta1?
无论如何,由于预期会出现 500 响应而出现异常,这就是 WebRequest 的工作原理。这是一个简短的演示程序:
open System
open System.ServiceModel
open System.ServiceModel.Web
[<ServiceContract>]
type IMyContract =
[<OperationContract>]
[<WebGet(UriTemplate="/Returns500")>]
abstract Returns500 : unit -> unit
[<OperationContract>]
[<WebGet(UriTemplate="/Returns201")>]
abstract Returns201 : unit -> unit
type MyService() =
interface IMyContract with
member this.Returns500() =
WebOperationContext.Current.OutgoingResponse.StatusCode <-
System.Net.HttpStatusCode.InternalServerError
member this.Returns201() =
WebOperationContext.Current.OutgoingResponse.StatusCode <-
System.Net.HttpStatusCode.Created
let addr = "http://localhost/MyService"
let host = new WebServiceHost(typeof<MyService>, new Uri(addr))
host.AddServiceEndpoint(typeof<IMyContract>, new WebHttpBinding(), "") |> ignore
host.Open()
open System.Net
let url500 = "http://localhost/MyService/Returns500"
let url201 = "http://localhost/MyService/Returns201"
let async_value (url:string) =
async {
let req = WebRequest.Create(url)
let! rsp = req.AsyncGetResponse()
return (rsp :?> HttpWebResponse).StatusCode
}
let status = Async.RunSynchronously(async_value url201)
printfn "%A" status
try
let status = Async.RunSynchronously(async_value url500)
printfn "%A" status
with e ->
printfn "%s" (e.ToString())
Run Code Online (Sandbox Code Playgroud)