从F#中使用时如何忽略C#等待任务?

时间:2019-05-11 22:58:53

标签: .net-core f# async-await

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

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>。我只想在F#方法中等效地await使用此方法,但这会触发错误:

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

我已经检查了that answer on 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'

但是,不能摆脱那个想法吗?

2 个答案:

答案 0 :(得分:2)

您的async计算表达式返回Async<unit>。您需要实际运行计算。您可以使用Async.RunSynchronously来做到这一点。

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

尽管在这一点上,我认为计算表达式是多余的。会做同样的事情:

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

答案 1 :(得分:2)

此表达式的结果:

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

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

要告诉编译器您还可以,只需使用以下命令将值转换为()类型的unit类型(与其他语言的void类型类似)即可ignore函数。

现在查看您的async的主体,在您的旧代码中,最后一条语句为let! result = ...,并且在F#语法中无效。每个letlet!都是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