用F#实现C#异步接口

时间:2015-03-09 13:59:27

标签: c# asynchronous interface f#

我必须用F#实现一个C#接口。接口和我必须使用的许多方法都是用C#编写的,并且非常重视异步。

从C#移植到F#的示例代码:

public async Task CloseAsync(PartitionContext context, CloseReason reason)
{
    Console.WriteLine(string.Format("Processor Shuting Down.  Partition '{0}', Reason: '{1}'.", this.partitionContext.Lease.PartitionId, reason.ToString()));
    if (reason == CloseReason.Shutdown)
    {
        await context.CheckpointAsync();
    }
}

这可能有问题,因为F#和C#不使用相同的异步模式或类型。上面的函数是我需要实现的接口的一部分。我的问题在于我如何以这样的方式等待context.CheckpointAsync() F#,它仍会返回Task

这是我试图去的方向,但它不起作用。 context.CheckpointAsync返回Task<a>而不是Task。另外,其他情况如何,预计不会进行任何操作?

interface IEventProcessor with
    member this.CloseAsync(context:PartitionContext, reason:CloseReason) =
        match reason with
        | CloseReason.Shutdown -> context.CheckpointAsync() |> Async.AwaitTask
        | _ -> ()

3 个答案:

答案 0 :(得分:1)

任务也是IAsyncResult,这意味着您可以使用Async.AwaitIAsyncResult并忽略输出。

将其全部包含在异步计算表达式中,将其作为任务&lt; unit&gt;启动。然后转向任务。

interface IEventProcessor with

    member __.CloseAsync(context : PartitionContext, reason : CloseReason) = 
        async { 
            if reason = CloseReason.Shutdown then 
                do! context.CheckpointAsync() |> Async.AwaitIAsyncResult |> Async.Ignore
        }
        |> Async.StartAsTask :> Task

答案 1 :(得分:0)

问题是在C#中它的返回类型为Task而不是Task<T>。在一个完美的世界中,C#可能有Task<void>

F#3.x内置了从Task<T>Async<T>但不是从TaskAsync<T>的绑定。在SO上有样本,例如How to Async.AwaitTask on plain Task (not Task<T>)?

无论如何,看到你得到的确切错误会很有帮助但是看起来你的错误就是你正试图Async.AwaitTask(它将返回Async<T>)但接口必须是Task。所以你可以完全摆脱Async.AwaitTask()

然后你将得到另一个错误,匹配案例不会占用,即Shutdown分支返回Task,而另一个分支返回unit。您需要更改它以返回Task

答案 2 :(得分:0)

您可以避免使用异步并直接从CheckpointAsync返回任务:

match reason with
| CloseReason.Shutdown -> context.CheckpointAsync() :> Task
| _ -> Task.CompletedTask