Итак, немного поработав с моделью Async в F#, я думаю, что обдумал ее и ее отличия от модели Task в C#. Одна из вещей, которые мне действительно нравятся в том, как они взаимодействуют, это Async.AwaitTask:

...
public Task<int> SomeCsharpApiAsync() {
    ...
}
...
let someFsharpAsyncCode = async {
    let! someResult = Async.AwaitTask (SomeClass.SomeCsharpApiAsync())
    return someResult
}

В приведенном выше коде строка, вызывающая AwaitTask, не только ожидает завершения задачи, но и присваивает ее результат переменной someResult в операции, которую я считаю атомарной. Очень аккуратный!

Однако у меня возникла проблема с достижением того же (атомарность, поэтому отсутствие условий гонки) при использовании Task.WhenAny:

...
public Task<int> SomeCsharpApiAsync(string someParam) {
    ...
}
...
let someFsharpAsyncCode = async {
    let task1 = SomeClass.SomeCsharpApiAsync "foo"
    let task2 = SomeClass.SomeCsharpApiAsync "bar"
    let! fastestTask = Async.AwaitTask (Task.WhenAny([task1;task2]))
    return fastestTask.Result
}

Проблема с приведенным выше кодом заключается в том, что операция AwaitTask возвращает задачу (самую быструю), а не результат, поэтому это дополнительный уровень косвенности, который я разрешаю, вызывая .Result позже. Но я нашел проблемы по этому поводу, виновником которых, я думаю, являются условия гонки: самая быстрая задача может иметь какой-то результат в этот момент, но при получении ее результата мог быть запрошен (отменен) маркер отмены задачи! Или самая быстрая задача была быстрее, потому что на самом деле та была отменена быстрее? Я не уверен, и я немного не понимаю, как понять, что здесь происходит.

Может быть, я могу вообще избежать этой проблемы, используя альтернативу F# Task.WhenAny в C#?

1
knocte 19 Окт 2019 в 09:53

1 ответ

Посмотрите, может ли эта реализация Async.WhenAny решить вашу проблему: https://github.com/tpetricek/ TryJoinads/blob/master/src/FSharp.Joinads/Async.fs#L9

См. также этот блог: http://tomasp.net/blog/joinads-async- реализовать.aspx/

Этот пример очень похож на ваш код, но, возможно, есть небольшая разница: https://github.com/microsoft/fsharplu/blob/master/FSharpLu/Async.fs#L59

А вот еще один краткий пример с другой целью, но все же может быть полезен: http://www.fssnip.net/hx/title/AsyncAwaitTask-with- тайм-ауты

0
Scott Hutchinson 19 Окт 2019 в 20:04
Спасибо, я посмотрю на следующей неделе и дам отзыв!
 – 
knocte
19 Окт 2019 в 21:18