2009-08-25 31 views
5

Tôi đang cố gắng sử dụng quy trình công việc không đồng bộ trong F # để tìm nạp một số yêu cầu web.Yêu cầu web không đồng bộ F #, xử lý ngoại lệ

Tuy nhiên, một số yêu cầu của tôi đôi khi trả lại lỗi (ví dụ: http 500) và tôi không biết cách xử lý việc này. Có vẻ như chương trình F # của tôi bị kẹt trong một vòng lặp vô hạn khi chạy trong trình gỡ rối.

Tôi có thể thiếu một số nội dung, khiến các ví dụ tôi thấy không biên dịch ra khỏi hộp. Điều đầu tiên tôi phát hiện ra rằng đã giúp được chút mã này:

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

và sau đó tôi có chút tôi mã để lấy yêu cầu, mà là khá chuẩn từ các ví dụ tôi đã nhìn thấy:

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

và sau đó tôi cố gắng để có được những kết quả:

let status = Async.RunSynchronously(async_value) 

Nhưng khi tôi chạy chương trình của tôi trong chương trình gỡ rối, nó phá vỡ tại req.EndGetResponse vì máy chủ trở lại lỗi máy chủ nội bộ 500. Nếu tôi tiếp tục chỉ tiếp tục execu tion, nó được trong một vòng funky, phá vỡ tại req.EndGetResponse (đôi khi một số liên tiếp), và tại cho status = Async.RunSynchronously (async_value).

Làm cách nào để khắc phục sự cố ngoại lệ để tôi có thể nhận mã trạng thái của mình? Ngoài ra, tôi có cần loại điều tôi đã làm ở trên không? Hoặc tôi thiếu một số thư viện/dll cho F #/VS 2010 Beta 1, trong đó điều này đã là một phần của?

Tôi thực sự chạy một số yêu cầu song song, sử dụng Async.RunSynchronously (Async.Parallel (my_array_of_async_values)), mặc dù tôi không nghĩ rằng điều đó liên quan đến vấn đề ngoại lệ mà tôi đang gặp phải.

Thực tế các ví dụ tôi đã đi qua chỉ sử dụng Async.Run hơn Async.RunSynchronously có lẽ là một chỉ báo tôi đang thiếu một cái gì đó ... =/

Trả lời

2

Nó bây giờ được gọi là 'AsyncGetResponse' (không còn 'GetResponseAsync') . Và 'Run' đã được đổi tên thành 'RunSynchronously'. Vì vậy, tôi không nghĩ rằng bạn đang thiếu bất cứ điều gì đáng kể ở đây, chỉ cần thay đổi tên trong bản phát hành mới nhất.

Cài đặt trình gỡ lỗi của bạn liên quan đến "Công cụ \ Tùy chọn \ Gỡ lỗi \ Chung \ Bật Chỉ mã của tôi" và "Gỡ lỗi \ Ngoại lệ" (ví dụ: đặt thành ngắt khi có bất kỳ ngoại lệ CLR đầu tiên nào được ném hay không)? Tôi không rõ ràng nếu câu hỏi của bạn liên quan đến hành vi của chương trình, hoặc hành vi công cụ VS (âm thanh như sau). Điều này còn bị xáo trộn bởi thực tế rằng điểm ngắt/gỡ lỗi 'vị trí' trong F # Beta1 có một số lỗi, đặc biệt là về quy trình công việc không đồng bộ, có nghĩa là hành vi bạn thấy trong trình gỡ lỗi có thể hơi lạ một chút ngay cả khi chương trình đang thực thi đúng cách .. .

Bạn đang sử dụng VS2008 CTP hoặc VS2010 Beta1?

Trong mọi trường hợp, nó xuất hiện ngoại lệ do phản hồi 500 được mong đợi, đây là cách hoạt động của WebRequest. Dưới đây là một chương trình giới thiệu ngắn:

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

Vâng, tôi thấy những gì tôi đã làm sai. Nó cũng là một phần hành vi dụng cụ (vs2010b1) liên quan đến sự kỳ quặc gỡ lỗi ngoại lệ. Tôi đã cố gắng chỉ lấy Mã trạng thái, phần duy nhất của phản hồi mà tôi thậm chí còn quan tâm, mà không xử lý ngoại lệ. – jessicah

1

Bạn có thể dùng thử ... với bên trong async để bắt ngoại lệ:

let async_value = 
    async { 
     let req = WebRequest.Create("http://unknown") 
     try 
      let! resp = req.AsyncGetResponse() 
      return "success" 
     with 
     | :? WebException as e -> return "failure" 
    } 
Các vấn đề liên quan