Мой вопрос очень прост. Пожалуйста, обратите внимание на скриншоте:F # не может поймать TimeoutException
Как это могло произойти? Я прямо поставил вызов Async.RunSyncronously в try ... with
.
Мой вопрос очень прост. Пожалуйста, обратите внимание на скриншоте:F # не может поймать TimeoutException
Как это могло произойти? Я прямо поставил вызов Async.RunSyncronously в try ... with
.
try/with
в F рабочих процессах # асинхронных не отображается непосредственно CLR защищенных блоки - вместо этого, если исключения возникают в коде пользователя, код библиотеки будет поймать его и изменить маршрут к продолжению ближайшей ошибки (которая может быть т.е. with block
, finally block
, продолжение пользовательской ошибки, поставляемое в Async.StartWithContinuations
и т. д.). Это приводит к тому, что отладчик может сообщать о необработанных исключениях в коде пользователя, которые могут обрабатываться и обрабатываться позже.
Отрывок ниже сообщает подобную ошибку в отладчике, но тем не менее, выполнение завершается успешно
let error(): int = raise (System.TimeoutException())
let run() = async {
try
let result = error()
return result
with
:? System.TimeoutException -> return -1
}
let r = Async.RunSynchronously (run())
printfn "%d" r
Вау, это действительно интересно. Это побочный эффект реализации вычислительного выражения Async? И не могли бы вы предложить, что было бы лучшим способом поймать это проклятое исключение? Правильно ли это, что я должен перевести его в 'StartWithContinuations'? – Rustam
Попробуйте это:
let withTimeout (timeOut: option<int>) (operation: Async<'x>) : Async<option<'x>> =
match timeOut with
| None -> async {
let! result = operation
return Some result
}
| Some timeOut -> async {
let! child = Async.StartChild (operation, timeOut)
try
let! result = child
return Some result
with :? System.TimeoutException ->
return None
}
Вы не должны использовать Async.RunSynchronously
в async
блоков, так как это делает для неоптимального использования собственных потоков и может привести к stack overflows. Async.RunSynchronously
предназначено для выполнения вычислений вне таких вычислений Async
. В блоке async
вы можете использовать простые let!
и do!
или, например, Async.StartChild
для запуска Async
вычислений. Это обеспечивает более эффективное использование собственных потоков и не страдает от подобных проблем с потенциальными переполнениями стека.
+1 Большое спасибо, это работает, я буду использовать вашу версию. Хотя по-прежнему интересно, почему моя версия не работает – Rustam
Может быть, я не понимаю, что правильно, но я подумал, что, делая это, я делаю так: 'async' начинается новый thread, и этот поток ждет завершения операции 'operation'. И это нормально для меня. Я мог бы использовать 'let!' Вместо этого, но 'let' не позволяет указывать тайм-аут, и для этого я и стремился. – Rustam
Да, это так. Проблема может возникнуть из-за того, что моя 'операция' вызывает некоторые методы COM-объекта, и это всегда является источником сбоев. Но я не могу быть уверен в этом. – Rustam