Próbuję wykonać asynchroniczne żądanie WWW na adres URL, który zostanie zwrócony, jeśli żądanie będzie trwało zbyt długo. Używam asynchronicznego workflow F # i biblioteki System.Net.Http, aby to zrobić.Obliczenia asynchroniczne nie przechwytują OperationCancelledException
Nie mogę jednak uchwycić wyjątku Task/OperationCancelledExceptions, które zostały podniesione przez bibliotekę System.Net.Http w przepływie pracy async
. Zamiast tego, jest wyjątek w metodzie Async.RunSynchronously, jak widać w tym ślad stosu:
> System.OperationCanceledException: The operation was canceled. at
> Microsoft.FSharp.Control.AsyncBuilderImpl.commit[a](Result`1 res)
> at
> Microsoft.FSharp.Control.CancellationTokenOps.RunSynchronously[a](CancellationToken
> token, FSharpAsync`1 computation, FSharpOption`1 timeout) at
> Microsoft.FSharp.Control.FSharpAsync.RunSynchronously[T](FSharpAsync`1
> computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken)
> at <StartupCode$FSI_0004>[email protected]()
kodu:
#r "System.Net.Http"
open System.Net.Http
open System
let readGoogle() = async {
try
let request = new HttpRequestMessage(HttpMethod.Get, "https://google.co.uk")
let client = new HttpClient()
client.Timeout <- TimeSpan.FromSeconds(0.01) //intentionally low to always fail in this example
let! response = client.SendAsync(request, HttpCompletionOption.ResponseContentRead) |> Async.AwaitTask
return Some response
with
| ex ->
//is never called
printfn "TIMED OUT"
return None
}
//exception is raised here
readGoogle()
|> Async.RunSynchronously
|> ignore
W ogóle, wyjątki są śmieszne z asynchronicznym autonomicznym. Chcesz użyć 'Async.Catch'. Dziwne zachowanie jest spowodowane, gdy wyjątek zostanie ponownie wyświetlony w głównym wątku, powodując nieparzysty ślad stosu. –
Próbowałem pisać to w stylu Async.Catch i problem nadal występuje. Inną rzeczą jest to, że jeśli zostanie zgłoszony inny typ wyjątku, zostanie złapany poprawnie. Zastanawiam się, czy moduł Async obsługuje tokeny anulowania może być wadliwy - być może źle interpretuje wyjątek jako żądanie anulowania do modułu. – WiseGuyEh