如果我已经有了像 epoll / kqueue / IOCP 这样的非阻塞 IO,为什么还需要 async / await?

Why do I need async / await if I already have non-blocking IO like epoll / kqueue / IOCP?

我有使用非阻塞 IO 库 epoll 及其高级抽象 libuv 的经验,所以当我开始学习 Rust 时,我寻找 Rust 等价物并找到了 Mio。 Mio 以我对非阻塞 IO 的理解方式工作,并且我很熟悉。我可以轻松地使用这种 API 来构建使用多个线程甚至单个线程的高性能服务器应用程序。

Rust 1.39 带来了 async / await 语法。我已经阅读了一些关于它的文章和文档,感觉就像协程。我知道 .await 可以用来产生 CPU 在同一个线程中做其他事情,但是没有简单的方法可以动态地将代码调度到该线程中的 运行,它不会'不像 epoll 这样的事件方式工作,我可以用它提前注册事件并在这些事件发生时得到通知。

async / await 打开和读取文件的示例对我来说没有意义,因为在 .await 之后我无事可做,但 等待 内容可用,所以我仍在阻塞,根本没有async

如果我使用像 Mio 或 unsafe epoll 这样的非阻塞 IO,我还需要 async / await 吗?如果不是,在什么情况下应该使用async / await

If I use non-blocking IO like Mio or unsafe epoll, do I still need async / await?

不需要async/await:你有代码可以做什么你想要,你乐于助人,它不用async/await。您没有明显的理由更改代码。您以多种方式陈述:

Mio works the way I understand

[Mio] is familiar to me.

I can easily use this kind of API

关于函数,可以问同样风格的问题。函数并不是严格需要的,因为我们可以在任何使用它的地方复制粘贴代码。代码完成了某些人想要的,某些人对此很满意,而且它没有使用函数。此开发人员没有明显的理由更改其代码。


Yes — 一般来说,大多数 Rust 开发人员在尝试编写异步代码时会使用 async / await(甚至可能在他们尝试编写异步代码时)不应该)。这些关键字主要是用于创建 future 的语法糖。在引入特殊语法之前,Futures 已经在 Rust 生态系统中存在了很长时间,因此甚至不需要语法。但是,它确实使创建期货更简单。

Futures 是异步工作的抽象,最终由 执行器 驱动。可以置于抽象之下的事物之一是基于事件的 IO 库。库通知执行者库管理的 IO 句柄之一发生了某些变化,这导致执行者恢复未来,这可能会意识到它已经完成。

Mio 被一些最常见的期货相关 crate 使用,例如 tokio or async-std。 Mio 文档甚至建议将它与 futures 一起使用:

This is a low level library, if you are looking for something easier to get started with, see Tokio.

另请参阅: