首页 > 解决方案 > 从 F# 消费时如何忽略 C# 等待任务?

问题描述

我正在尝试使下面的代码正常工作

type Message = {
    Text: string
}

[<EntryPoint>]
let main argv =
    use bus = RabbitHutch.CreateBus("host=localhost")
    async {
        let! result = bus.PubSub.PublishAsync({Text = "text"}) |> Async.AwaitTask
    }
    0

知道PublishAsync返回Task<unit>。我只是想await在 F# 方法中等效地使用此方法,但这会触发错误:

Program.fs(14, 5): [FS0010] Unexpected symbol '}' in expression

我已经检查了 SO 上的答案,不确定我应该做什么,添加|> ignore似乎没有做任何事情。

[编辑]

我添加了一个ignore

type Message = {
    Text: string
}

[<EntryPoint>]
let main argv =
    use bus = RabbitHutch.CreateBus("host=localhost")
    async {
        let! result = bus.PubSub.PublishAsync({Text = "text"}) |> Async.AwaitTask
        result |> ignore
    }
    0

但现在我收到以下警告:

Program.fs(10, 5):[FS0020]这个表达式的结果有类型'Async<unit>'并且被隐式忽略。考虑使用'ignore'显式丢弃此值,例如'expr |> ignore',或'let'将结果绑定到名称,例如'let result = expr'

但是不能摆脱那个,知道吗?

标签: .net-coref#async-await

解决方案


这个表达式的结果:

async {
    let! result = bus.PubSub.PublishAsync({Text = "text"}) |> Async.AwaitTask
    result |> ignore
}

Async<unit>类型的值。在 F# 和函数式编程中,每个表达式都应该对更大表达式的结果做出贡献,否则很可能是错误的。因此,您的编译器报告了警告。

要告诉编译器你可以接受,只需使用函数将值转换为类型的()unit(类似于void其他语言中的类型)ignore

现在查看旧代码的主体async,最后一条语句是let! result = ...,它在 F# 语法中是无效的。每个letorlet!是的缩写形式,let name=... in someExpression但这里没有表达式,除了}这就是编译器说Unexpected symbol '}' in expression.

你通过管道解决result了这个问题ignore。没关系,因为这是一个有效的表达式。

现在考虑您的新代码,您可以忽略Async<unit>以消除警告,但这使您async胡说八道。您声明了async,但没有执行它。可能您需要使用以下Async.RunSynchronously功能执行它:

async {
    let! result = bus.PubSub.PublishAsync({Text = "text"}) |> Async.AwaitTask
    result |> ignore
}
|> Async.RunSynchronously 

由于result是一个unit值,您可以使用以下命令清理代码do!

async {
    do! bus.PubSub.PublishAsync({Text = "text"}) |> Async.AwaitTask
}
|> Async.RunSynchronously 

甚至更清洁:

bus.PubSub.PublishAsync({Text = "text"})
|> Async.AwaitTask
|> Async.RunSynchronously

推荐阅读