我试图使用异步工作流在F#中获取一些Web请求。

不过,我的一些要求偶尔会返回错误(例如HTTP 500),我不知道该如何处理这个问题。在调试器中运行时,它看起来像我的F#程序陷在一个无限循环。

我可能错过了一些东西,造成的例子,我看到没有编译开箱。第一件事,我发现,帮助了这段代码:

type System.Net.WebRequest with
  member req.GetResponseAsync() =
    Async.BuildPrimitive(req.BeginGetResponse, req.EndGetResponse)

和然后我有我的码位,以获取请求,这是非常标准的从我所看到的例子:

let async_value = async {
  let req = WebRequest.Create(url)
  let! rsp = req.GetResponseAsync()
  return (rsp :?> HttpWebResponse).StatusCode
}

然后我尝试得到的结果:

let status = Async.RunSynchronously(async_value)

但是,当我在调试器中运行我的程序,它打破了在req.EndGetResponse因为服务器返回内部服务器错误500。如果我一直只是继续执行,它会在一个时髦的循环,在req.EndGetResponse(有时连续几个)打破,和在设status = Async.RunSynchronously(async_value)。

我如何得到解决异常问题,所以我可以得到我的状态代码?另外,我还需要类型的事情我上面做?还是我失去了F#的一些库/ DLL / VS 2010 Beta 1中,这是其中已经的一部分?

我其实并行运行多个请求,使用Async.RunSynchronouslyAsync.Parallel(my_array_of_async_values)),但我不认为这是关系到我有异常问题。

我遇到的例子中只使用Async.Run而不是Async.RunSynchronously,原因可能是我想的东西的指标... = /

有帮助吗?

解决方案

它现在被称为 'AsyncGetResponse'(不再 'GetResponseAsync')。和“运行”更名为“RunSynchronously”。所以,我不认为你错过任何实质性这里,仅举在最新版本中的变化。

什么是关于“工具\选项\调试\一般\启用仅我的代码”和“调试\例外”您的调试程序设置(例如设置任何时候第一次机会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())

其他提示

您可以使用try ...与异步内捕获异常:

let async_value =
    async {
        let req = WebRequest.Create("http://unknown")
        try
            let! resp = req.AsyncGetResponse()
            return "success"
        with
        |   :? WebException as e -> return "failure"
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top