Асинхронное ожидание в F#

Я переписываю часть C# в этой лабораторной работе на F#: https://github.com/Microsoft/TechnicalCommunityContent/tree/master/IoT/Azure%20Stream%20Analytics/Session%202%20-%20Hands%20On

Я выполняю Упражнение 6, № 17 — создание типа SimpleEventProcessor.
Я хочу реализовать метод CloseAsync

C#

async Task IEventProcessor.CloseAsync(PartitionContext context, CloseReason reason)
    {
        Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason);
        if (reason == CloseReason.Shutdown)
        {
            await context.CheckpointAsync();
        }
    }

а я начал так:

member this.CloseAsync(context, reason) = 
    Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason)
    match reason with 
    | CloseReason.Shutdown -> await context.CheckpointAsync()
    | _ -> ()

но у меня 2 вопроса:

  1. Как вернуть await в мире F#?
  2. Как мне вернуть НЕ регистр -> С# просто игнорирует эту возможность.

person Jamie Dixon    schedule 25.05.2017    source источник


Ответы (1)


  1. Если значение имеет тип Async<'T>, вы можете просто вернуть его без ключевого слова. Если он имеет тип Task или Task<'T>, вы можете сделать |> Async.AwaitTask.

  2. Вы можете вернуть async { return () }.

Итак, вы получаете это:

member this.CloseAsync(context, reason) = 
    Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason)
    match reason with 
    | CloseReason.Shutdown -> context.CheckpointAsync() |> Async.AwaitTask
    | _ -> async { return () }

Другая возможность — поместить весь блок в рабочий процесс async и использовать return! для 1 и return для 2:

member this.CloseAsync(context, reason) = 
    async {
        Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason)
        match reason with 
        | CloseReason.Shutdown -> return! context.CheckpointAsync() |> Async.AwaitTask
        | _ -> return ()
    }

На самом деле, использование асинхронного рабочего процесса позволяет вам отбросить регистр () аналогично C#:

member this.CloseAsync(context, reason) = 
    async {
        Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason)
        if reason = CloseReason.Shutdown then
            return! context.CheckpointAsync() |> Async.AwaitTask
    }
person Tarmil    schedule 25.05.2017
comment
IEventProcessor CloseAsync возвращает задачу. Так | CloseReason.Shutdown -> context.CheckpointAsync() работает. Нужно выяснить, как вернуть пустую задачу - person Jamie Dixon; 25.05.2017
comment
Это сделало это: сопоставьте причину с | CloseReason.Shutdown -> context.CheckpointAsync() | _ -> Задача.ВыполненнаяЗадача - person Jamie Dixon; 25.05.2017
comment
Ах, извините, я неправильно понял ваш вопрос, почему-то я подумал, что вы переходите с Task на Async в дополнение к переходу с C # на F #. - person Tarmil; 25.05.2017
comment
Если вы используете асинхронный F# вместо Task, разве не принято называть метод AsyncClose вместо CloseAsync? - person Bent Tranberg; 26.05.2017