У меня есть функция, которая будет делать некоторые вещи асинхронно, но не предоставляет асинхронность и вместо этого будет вызывать обратный вызов с результатом по завершении. Я хочу превратить это в асинхронный режим и придумал этот код, но мне это кажется не совсем правильным. Есть способ сделать это лучше?

async { 
    let ev = Event<_>()
    someAsyncExternalCodeThatWillCallTheCallbackWhenDone(fun value -> ev.Trigger value)
    let! value = Async.AwaitEvent(ev.Publish)
    return value 
}

Есть ли преимущества использования Observable или ManualResetEvent вместо Event в этом сценарии?

3
Gustavo Guerra 21 Мар 2013 в 18:42

1 ответ

Лучший ответ

Я думаю, что идиоматическое решение в этом случае - использовать Async.FromContinuations:

Async.FromContinuations(fun (cont, econt, ccont) ->
  someAsyncExternalCodeThatWillCallTheCallbackWhenDone(cont))

Функция FromContinuations также позволяет обрабатывать исключения (вызывать econt, если возникает исключение) или отмену (и вы можете рассматривать это как базовый способ создания асинхронных вычислений).

Тем не менее, я не думаю, что есть что-то плохое в использовании событий. Код с событиями реализует почти ту же логику (я думаю), но более сложным образом.

4
Tomas Petricek 21 Мар 2013 в 18:58
Это stackoverflow.com/questions/3701861/… все еще актуален? (относительно вашего ответа на этот вопрос, в частности, об использовании Event с AwaitEvent и утечками памяти)
 – 
MisterMetaphor
22 Мар 2013 в 14:52