我还没有找到指定操作超时的方法 - 请参阅代码段以了解我尝试实现的目标。
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 :(得分:0)
我有这个经过充分测试的代码,但它的定位是HttpWebRequest
而不是WebClient
;我相信它可以完全适合您的需求:
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 ())