2016-05-07 29 views
0

操作のタイムアウトを指定する方法が見つかりませんでした。コードスニペットで何を達成しようとしているのかを確認してください。WebClient.AsyncDownloadString() - タイムアウトを指定する方法はありますか?

type ResponseKind = 
    | Json of string 
    | Error of Exception 
    | Timeout 

let download (wclient : WebClient) (timeout : int option) (base_url : Uri) (sub_url : string) : Async<ResponseKind> = 
    async { 
     let target_uri = Uri(base_url, sub_url) 
     try 
      let! result = wclient.AsyncDownloadString(target_uri) 
      return ResponseKind.Json result 
     with 
     | :? TimeoutException -> 
      return ResponseKind.Timeout 
     | _ as ex -> 
      return ResponseKind.Error ex 
    } 

ここで、私は同じことを達成するために他にも多くの方法があることを認識しています。代わりにWebRequestを使用してください。しかし、たぶんそれは私の単純な見落としであり、操作のタイムアウトを設定する方法を見つけ出すことはできません。

アイデア?私に代わって

更新

詳しい調査の結果、実行すべきタスクと並行して、タイムアウトタスクを使用していますFSSnippetに私を導きました。私のコンテキストでそのアプローチを再利用

は、私のコードの修正版が得られた:今

type ResponseKind = 
    | Json of string 
    | Error of Exception 
    | Timeout 

let await_download_with_timeout (task : Task<string>) (timeout : int) : Async<ResponseKind>= 
    async { 
     use cts = new CancellationTokenSource() 
     use timer = Task.Delay (timeout,cts.Token) 
     let! completed = 
      Task.WhenAny(task,timer) 
      |> Async.AwaitTask 
     if completed = (task :> Task) 
     then 
      cts.Cancel() 
      let! result = Async.AwaitTask task 
      if task.IsCompleted 
      then 
       return ResponseKind.Json result 
      else 
       return ResponseKind.Error (task.Exception) 
     else 
      return ResponseKind.Timeout 
    } 

let download (wclient : WebClient) (timeout : int option) (base_url : Uri) (sub_url : string) : Async<ResponseKind> = 
    async { 
     let target_uri = Uri(base_url, sub_url) 
     try 
      match timeout with 
      | Some t -> 
       let dtask = wclient.DownloadStringTaskAsync(target_uri) 
       let! result = await_download_with_timeout dtask t 
       return result 
      | None -> 
       let! result = wclient.AsyncDownloadString(target_uri) 
       return ResponseKind.Json result 
     with 
     | :? TimeoutException -> 
      return ResponseKind.Timeout 
     | _ as ex -> 
      return ResponseKind.Error ex 
    } 

を、残りの問題は間違って何か他の私の検出が大丈夫であれば、私はわからないということです。

+0

http://stackoverflow.com/questions/1789627/how-to-change-the-timeout-on-a-net-webclient-object - Dang - 質問を書く前にこれを見つけられなかったので、私の質問は重複しています - ごめんなさい。 – BitTickler

+0

これは非同期では機能しない可能性があります。 – Ringil

答えて

0

このコードはよくテストされていますが、WebClientではなくHttpWebRequestに対応しています。私はそれは自明のニーズに合っすることができます確信している:

type System.Net.WebRequest with 
    member req.AsyncGetResponseWithTimeout() = 
    let impl = async { 
     let iar = req.BeginGetResponse (null, null) 
     let! success = Async.AwaitIAsyncResult (iar, req.Timeout) 
     return if success then req.EndGetResponse iar 
      else req.Abort() 
        raise (System.Net.WebException "The operation has timed out") } 
    Async.TryCancelled (impl, fun _ -> req.Abort()) 
関連する問題