Rust Tokio:从同步闭包中调用异步函数

3
我有以下问题: 我试图从async函数中调用sync闭包,但是sync闭包需要稍后调用另一个async函数。
由于在目前的情况下async闭包不稳定,所以我不能创建它们: error[E0658]: async closures are unstable 所以我必须通过某种方式来解决这个问题。
我找到了一些相关的问题,例如这个,但是当我尝试实现时,我收到了以下错误:
Cannot start a runtime from within a runtime. 
This happens because a function (like `block_on`)
 attempted to block the current thread while the 
thread is being used to drive asynchronous tasks.'

这里是一个playground链接,希望可以展示我遇到的问题。

如标题所述,我正在使用tokio。


你可以使用闭包返回异步块 - || async { ... } 而不是 async || { ... } - Cerberus
具体来说,这是您的游乐场,建议进行更改:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=cc987ff5c41352ddc447a6724ae6abc8 - Cerberus
@Cerberus 非常感谢,看起来现在这是正确的方法。只是为了给未来的读者留下评论,现在由于闭包返回异步块(而不是之前的正常方式),因此应该使用 .await 调用闭包。 - Blomex
1个回答

2
正如错误消息所述,Tokio不允许您使用嵌套运行时。
在Tokio的文档中有一个关于Mutex的部分,其中包含以下内容(link):

在异步代码中使用普通标准库中的Mutex通常是可以的并且更好。[...] 异步Mutex相对于阻塞Mutex的特点是可以在.await点跨越锁定Mutex,但这对于数据来说很少是必要的。

此外,在Tokio的mini-Redis示例中:
一个Tokio互斥锁主要是用于在.await yield点之间保持锁的情况下使用。所有其他情况通常最好使用std mutex。如果关键部分不包括任何异步操作但很长(CPU密集型或执行阻塞操作),那么整个操作,包括等待互斥锁,都被认为是“阻塞”操作,并且应该使用tokio::task::spawn_blocking
如果Mutex是您同步调用中唯一需要的async内容,那么将其设置为阻塞Mutex可能更好。在这种情况下,您可以通过首先调用try_lock(),如果失败,则尝试通过spawn_blocking在阻塞上下文中锁定它来从async代码中锁定它。

这并没有真正帮到我,因为在互斥锁后面有一个async套接字,我从异步函数和提到的闭包中都会写入它。我猜我可以将套接字变成同步的,然后从每个尝试写入此套接字的异步函数中调用阻塞生成,但那看起来很丑陋。 - Blomex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接