2009-08-25 18 views
5

Bazı web isteklerini almak için F # içinde async iş akışlarını kullanmaya çalışıyorum. Ancak, bazı isteklerim bazen geri dönen hatalardır (ör. Http 500) ve bunun nasıl ele alınacağını bilmiyorum. Hata ayıklayıcısında çalışırken F # programım sonsuz bir döngüde sıkışmış gibi görünüyor.F # async web isteği, özel durumlar ele alınması

Muhtemelen bazı şeyleri özlüyorum, çünkü gördüğüm örnekler kutunun dışında derlemediler. oldu yardımcı buldum ilk şey bu kod bit:

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

: o zaman ben gördüğüm örneklerden oldukça standart istekleri getirmek için kod rolümü var

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

ve ve sonra sonuç elde etmeye çalışmak:

let status = Async.RunSynchronously(async_value) 

Ama ayıklayıcısında benim program çalıştırdığınızda Ben sadece devam execu tutarsanız sunucu iç sunucu hatası 500. döndürdü çünkü req.EndGetResponse de kırar Bu, req.EndGetResponse (bazen bir satırda birkaç kez) ile kırma ve status = Async.RunSynchronously (async_value) olsun, korkak bir döngü içinde alır.

Durum kodumu alabilmem için istisna sorununu nasıl çözebilirim? Ayrıca, yukarıda yaptığım şey tipine ihtiyacım var mı? Yoksa bu zaten bir parçası olan F #/VS 2010 Beta 1 için bir kütüphane/dll eksik mi?

Async.RunSynchronously (Async.Parallel (my_array_of_async_values)) işlevini kullanarak paralel olarak birkaç istek çalışıyorum, ancak bunun istisna sorunuyla ilgili olduğunu düşünmüyorum.

Ben sadece rastlamak ettik örnekler Async.Run yerine Async.RunSynchronously kullanmak aslında muhtemelen bir şey eksik bir göstergesidir ... =/

cevap

2

şu anda 'AsyncGetResponse' (artık 'GetResponseAsync') denir . Ve 'Run', 'RunSynchronously' olarak yeniden adlandırıldı. Bu yüzden burada önemli bir şeyi kaçırdığınızı düşünmüyorum, sadece son sürümdeki değişiklikleri adlandırın.

"Araçlar \ Seçenekler \ Hata Ayıklama \ Genel \ Sadece Kodum Etkinleştir" ve "Hata Ayıklama \ İstisnaları" ile ilgili hata ayıklayıcı ayarlarınız nelerdir (örneğin, herhangi bir ilk fırsat CLR kural dışı durumu atıldığında veya sonlandırıldığında kırılacak şekilde ayarlanmış)? Sorunuzun program davranışını veya VS takım davranışını içerip içermediğine emin değilim (ikincisine benziyor). Bu, F # Beta1'deki kesme noktası/hata ayıklama 'konumlarının' özellikle uyumsuz iş akışları ile ilgili bazı hatalara sahip olmasından da kaynaklanmaktadır. Bu da, hata ayıklayıcıda gördüğünüz davranışın program düzgün bir şekilde çalışsa bile biraz garip gelebileceği anlamına gelir.

VS2008 CTP veya VS2010 Beta1 kullanıyor musunuz?

Her durumda, 500 yanıt beklendiği için bir istisna ortaya çıkıyor, WebRequest bu şekilde çalışıyor. Burada kısa bir demo programı:

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()) 
+0

Evet, yanlış yaptıklarını görüyoruz. Ayrıca hata ayıklama garipliği ile ilgili olarak kısmen takım davranışı (vs2010b1) oldu. Sadece istisna olmaksızın, baktığım yanıtın tek parçası olan StatusCode'u almaya çalışmıştım. – jessicah

1

İstisnaları yakalamak için zaman uyumsuz iç ile ... deneyin kullanabilirsiniz:

let async_value = 
    async { 
     let req = WebRequest.Create("http://unknown") 
     try 
      let! resp = req.AsyncGetResponse() 
      return "success" 
     with 
     | :? WebException as e -> return "failure" 
    } 
İlgili konular