正确的使用方法!关键字来等待 Task<'a>

Proper way to use the do! keyword to await a Task<'a>

提问人:karanveer41 提问时间:11/4/2023 最后编辑:karanveer41 更新时间:11/6/2023 访问量:106

问:

我正在使用 F# 与异步 C# 类进行互操作。

我有一种情况,我需要调用一个返回泛型的方法,并异步等待它完成,然后忽略结果。Task<'a>

通过使用 F# 文档,我了解到您可以只用于等待非泛型 .do!Task

task {
    do! obj.workAsync() // where workAsync: () -> Task
}

真棒。但是当 的签名为 时,上述方法不起作用。workAsync() -> Task<'a>

所以我需要一些方法来转 a,我想出了两种方法(可能还有更多我不知道的)。Task<'a> -> Task

// variant 1
let toNonGenericTask (res: Task<'a>) : Task =
    task {
        let! _ = res
        ()
    }

// variant 2
let toNonGenericTask (res: Task<'a>) : Task =
    res.ContinueWith(fun (_: Task<'a>) -> ())


let processStuff () =
    task {
        do! obj.workAsync() |> toNonGenericTask // both variants work!
    }

我的问题是,首选哪个版本的函数?有没有其他方法可以在不使用自定义帮助程序函数的情况下执行相同的操作?toNonGenericTask


在考虑有用的回复后进行更新。

毕竟,我不需要使用辅助功能。通过简单地添加一个 upcast,我能够异步等待通用任务值,同时将其包装在另一个任务对象中,这是我需要做的。

它非常可读且简洁明了。

task {
    do! obj.workAsync() :> Task
}
F# 任务

评论


答:

1赞 Leaxe 11/4/2023 #1

您可以简单地使用 调用 ,就像在第一个示例中所做的那样:workAsync()let! _ = ...

let processStuff () =
    task {
        let! _ = obj.workAsync() // this works too!
    }

评论

0赞 karanveer41 11/5/2023
这会导致编译错误,指出“错误 FS0010:表达式中出现意外的符号 '}'...”当我在末尾添加 a 时,在行之后,它起作用了。()let!
1赞 Jim Foye 11/4/2023 #2

您不需要任务表达式来处理 ,也不需要将 映射到 或 order 来忽略结果。TaskTask<'T>Task

// Task
let task = obj.workAsync()
task.Wait()

// Task<'T>
let task = obj.workAsync()
task.Result // |> ignore if you don't care

评论

0赞 karanveer41 11/5/2023
不会并阻止主线程?task.Wait()task.Result
0赞 Jim Foye 11/5/2023
是的,没错。我在你问题的顶部解决了这个问题:“我有一个案例,我需要调用一个返回通用 Task<'a> 的方法,等待它完成,然后忽略结果。
1赞 Jim Foye 11/5/2023
因此,您真正想要的是等效于 Async.Ignore 的任务。查看此问题中的答案: stackoverflow.com/questions/71093379/how-to-ignore-a-task-in-f
0赞 karanveer41 11/6/2023
完全。一种非阻塞方式,用于等待通用任务完成,但忽略实际结果。我更新了我的问题,以反映我需要异步等待结果。
2赞 JL0PD 11/5/2023 #3

由于派生自 ,您可以简单地将其转换为非泛型类:Task<T>Task

let toNonGenericTask (t: Task<'a>) = t : Task

let foo () = task {
    let t = Task.FromResult 5
    do! t :> Task // upcast
    do! t : Task // specify type
    do! t |> toNonGenericTask // helper function, but it's too verbose in my opinion
}