Доброго времени,
есть список объектов с координатами для которых надо получить адрес, если его можно определить сервисом (геокодинг).
Список этих объектов довольно большой, хотелось бы обрабатывать асинхронно, с логированием того, что для этого объекта нет адреса (или сервис вернул ошибку).
Сделать асинхронный запрос благодаря многочисленным руководствам, не проблема:
async {
let request = HttpWebRequest.Create(url)
let! response = request.AsyncGetResponse()
use response = response
let stream = response.GetResponseStream()
use reader = new StreamReader(stream)
let! result= reader.AsyncReadToEnd()
return (id,result) (* id это id объекта, указывается выше по коду *)
}
|> Async.Catch
|> Async.RunSynchronously
|> function
| Choice1Of2 (id2,result2) -> (id2,result2)
| Choice2Of2 (ex : exn) -> (id,ex.Message)
проблема в том, что Async.RunSynchronously так же как и Async.StartWithContinuations вызываются немедленно, а мне хотелось бы сформировать лист Async и потом их вызвать c помощью Async.Parallel
Как быть в этой ситуации?
Re: [F#] Запуск асинхронных задач с обработкой ошибок
Здравствуйте, cadet354, Вы писали:
C>проблема в том, что Async.RunSynchronously так же как и Async.StartWithContinuations вызываются немедленно, а мне хотелось бы сформировать лист Async и потом их вызвать c помощью Async.Parallel C>Как быть в этой ситуации?
1) Почему бы не использовать try внутри async?
2) Почему бы не подготовить список в котором лежат элементы типра Async<Choice<(string*string),exn>> и запустить через Parallel ?
Re[2]: [F#] Запуск асинхронных задач с обработкой ошибок
Здравствуйте, achmed, Вы писали:
A>1) Почему бы не использовать try внутри async?
не кошерно A>2) Почему бы не подготовить список в котором лежат элементы типра Async<Choice<(string*string),exn>> и запустить через Parallel ?
а как получить список ошибок?
Re[3]: [F#] Запуск асинхронных задач с обработкой ошибок
Здравствуйте, cadet354, Вы писали:
C>Здравствуйте, achmed, Вы писали:
A>>1) Почему бы не использовать try внутри async? C>не кошерно
даже не знаю что сказать ...
A>>2) Почему бы не подготовить список в котором лежат элементы типра Async<Choice<(string*string),exn>> и запустить через Parallel ? C>а как получить список ошибок?
Parallel вернет список Choice<(string*string),exn>
Re[3]: [F#] Запуск асинхронных задач с обработкой ошибок
Здравствуйте, cadet354, Вы писали:
C>Здравствуйте, achmed, Вы писали:
A>>2) Почему бы не подготовить список в котором лежат элементы типра Async<Choice<(string*string),exn>> и запустить через Parallel ? C>а как получить список ошибок?
не понял, в чем проблема то? ПРимерно так (возможны опечатки — не проверял)
let ids = [1;2;3;4]
let results = ids
|> List.map (fun id -> async {
...
})
|> List.map Async.Catch
|> Async.Parallel
|> Async.RunSynchronously
|> List.ofArray
let errors = results |> List.choose (function
| Choice2Of2 e -> Some e
| _ -> None results)
Re: [F#] Запуск асинхронных задач с обработкой ошибок
Здравствуйте, cadet354, Вы писали:
C>Как быть в этой ситуации?
Использовать правильные языки.
Немерловая версия умеет такое из коробки.
По этим двум примерам думаю все поймешь.
Здравствуйте, Jack128, Вы писали:
J>Здравствуйте, cadet354, Вы писали:
C>>Здравствуйте, achmed, Вы писали:
A>>>2) Почему бы не подготовить список в котором лежат элементы типра Async<Choice<(string*string),exn>> и запустить через Parallel ? C>>а как получить список ошибок?
J>не понял, в чем проблема то? ПРимерно так (возможны опечатки — не проверял)
Здравствуйте, achmed, Вы писали:
A>Здравствуйте, cadet354, Вы писали:
C>>Здравствуйте, achmed, Вы писали:
A>>>1) Почему бы не использовать try внутри async? C>>не кошерно A>даже не знаю что сказать ...
видно придется именно так и сделать.
A>>>2) Почему бы не подготовить список в котором лежат элементы типра Async<Choice<(string*string),exn>> и запустить через Parallel ? C>>а как получить список ошибок? A>Parallel вернет список Choice<(string*string),exn>
а id вызвавшего ошибку?
Re[5]: [F#] Запуск асинхронных задач с обработкой ошибок
Здравствуйте, cadet354, Вы писали:
C>все дело в том, что мне надо знать какой id вызвал ошибку. C>Но за совет спасибо.
На немерле можно сделать так
list.Map((id, url) => (id, HttpGet(url).Start())).Iter((id, result) =>
{
match (result.GetResult())
{
| Value(value) => ...
| Exception(ex) => ...
| Canceled => ...
}
});
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: [F#] Запуск асинхронных задач с обработкой ошибок
Здравствуйте, cadet354, Вы писали:
C>Здравствуйте, Jack128, Вы писали:
J>>Здравствуйте, cadet354, Вы писали:
C>>>Здравствуйте, achmed, Вы писали:
A>>>>2) Почему бы не подготовить список в котором лежат элементы типра Async<Choice<(string*string),exn>> и запустить через Parallel ? C>>>а как получить список ошибок?
J>>не понял, в чем проблема то? ПРимерно так (возможны опечатки — не проверял)
C>все дело в том, что мне надо знать какой id вызвал ошибку.
Так почему бы не прицепить id к самому Async вместо его значения?
let second f = fun (x, y) -> x, f y
let uncurry f = fun (x, y) -> f x y
let ids = [1..4]
let results =
ids |>
List.map (fun id -> id, async { ... }) |>
List.unzip |>
(second
(Async.Catch |> List.map >>
Async.Parallel >>
Async.RunSynchronously >>
List.ofArray)) |>
(uncurry List.zip) |>
List.map
(function
| id, Choice1Of2 result -> (id, result)
| id, Choice2Of2 (ex : exn) -> (id, ex.Message))
Re[6]: [F#] Запуск асинхронных задач с обработкой ошибок
Здравствуйте, cadet354, Вы писали:
C>Здравствуйте, k.o., Вы писали:
C>>>все дело в том, что мне надо знать какой id вызвал ошибку.
KO>>Так почему бы не прицепить id к самому Async вместо его значения? C>честно говоря это слишком сложно для меня (даже прочитать с N-попытки)
На самом деле это почти не отличается от того, что предлагал