2009-08-25 23 views
5

F#で非同期ワークフローを使用して、いくつかのWebリクエストをフェッチしようとしています。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) 

しかし、私は、デバッガで私のプログラムを実行すると、私はちょうど継続execuを続ける場合は、サーバーが内部サーバーエラー500を返したため、それが req.EndGetResponseで壊し:その後、私は結果を取得しようそれは、 req.EndGetResponse(時には複数の行で)で破損し、let status = Async.RunSynchronously(async_value)で破損しています。

ステータスコードを取得できるように、例外の問題を回避するにはどうすればよいですか?また、私は上記のタイプのものが必要ですか?または、F#/ VS 2010 Beta 1のライブラリ/ DLLがなくなっていますが、これは既に一部ですか?

Async.RunSynchronouslyAsync.Parallel(my_array_of_async_values))を使用して実際に複数のリクエストを実行していますが、それは私が持っている例外の問題とは関係ありません。

私は遭遇してきた例はAsync.RunではなくAsync.RunSynchronouslyを使用するという事実は、おそらく私は何かが欠けてい指標である... =/

答えて

2

今では「AsyncGetResponse」(もはや「GetResponseAsync」)と呼ばれています。 「Run」は「RunSynchronously」に変更されました。だから私はあなたがここに何かを欠けているとは思わない、ちょうど最新リリースの名前の変更。

「Tools \ Options \ Debugging \ General \ Enable My 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()) 
+0

はい、私は私が間違って行っていたものを参照してください。例外デバッグの奇妙さに関するツールビヘイビアの一部(vs2010b1)でもありました。 私は、例外を処理することなく、私が気にしていた応答の唯一の部分であるStatusCodeを取得しようとしました。 – jessicah

1

let async_value = 
    async { 
     let req = WebRequest.Create("http://unknown") 
     try 
      let! resp = req.AsyncGetResponse() 
      return "success" 
     with 
     | :? WebException as e -> return "failure" 
    } 
関連する問題