前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Rust异步编程之Future初探

Rust异步编程之Future初探

作者头像
newbmiao
发布于 2024-01-10 06:25:56
发布于 2024-01-10 06:25:56
60100
代码可运行
举报
文章被收录于专栏:学点Rust学点Rust
运行总次数:0
代码可运行

RustFuture是用来实现异步编程的。今天我们围绕其了解下Rust的异步编程是如何构建。

Rustasync就能轻松创建开销很小的可异步执行的函数,在await时其才会被调度执行。

其比较轻量级,有别于异步多线程,依托在操作系统线程之上,构建大量并发则需要大量的线程资源,对资源的消耗比较大。

比如下边用async构建异步任务:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
async fn async_fn() {
    // handle async logic
}

#[tokio::main]
async fn main() {
    async_fn().await
}

文章目录

  • 状态机
  • 调度
  • 运行时
  • async
  • pin

状态机

async其实也是帮你自动实现了下边的Future trait,用结构体维护了一个状态机

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
trait Future {
    type Output;
    fn poll(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Self::Output>;
}

Future定义一个poll方法,可以查询异步任务状态。对于异步任务,有PendingReady两种状态,Pending时会让出控制,等待可以处理时再被唤醒继续处理,如此重复,直到Ready

我们来尝试通过实现一个DelayFuture了解这个状态流转的过程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::{Duration, Instant};

struct Delay {
    when: Instant,
}

impl Future for Delay {
    type Output = &'static str;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<&'static str> {
        if Instant::now() >= self.when {
            Poll::Ready("done")
        } else {
            // 还未ready,注册下一次唤醒
            cx.waker().wake_by_ref();
            Poll::Pending
        }
    }
}

#[tokio::main]
async fn main() {
    let when = Instant::now() + Duration::from_millis(3);
    let future = Delay { when };

    let out = future.await;
    assert_eq!(out, "done");
}

Delay每次poll时会检查,时间是否满足,满足则Ready,否则 schedule 下一次执行并返回Pending

状态机是有了,Future怎么调度呢?

调度

Rust需要运行时runtime来调度异步任务taskruntime负责调度,检查future的状态。

调度一般在Pending时会交出task的控制,并schedule下一次什么时候唤醒(wake)。

流程处理展开来说,常规Ready处理:

代码语言:javascript
代码运行次数:0
运行
复制

Pending时, future要被schedule下一次唤醒,而每次唤醒可能不会都是在同一个task上执行。这里用于唤醒的waker会在每次poll时以context传递下去,

代码语言:javascript
代码运行次数:0
运行
复制

运行时

了解了调度,我们再展开说下运行时。rust的运行时没在标准库中实现,需要依赖第三方的运行时,常用的有tokio

就比如如下的tokio宏实际是添加了一个多线程(multi thread)的运行时,会阻塞当前线程直到异步任务完成。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#[tokio::main]
async fn main() {
    println!("hello");
}

// tranform to
fn main() {
    tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .build()
        .unwrap()
        .block_on(async {
            println!("Hello world");
        })
}

当然也可以用单线程的运行时(current thread

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#[tokio::main(flavor = "current_thread")]
async fn main() {
    println!("Hello world");
}
// tranform to
fn main() {
    tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .unwrap()
        .block_on(async {
            println!("Hello world");
        })
}

async

其实一般很少直接去实现Future trait, 直接使用async去自动实现Future trait就足够了。上边Delay完全可以这么实现,简洁且高效

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use std::sync::Arc;
use std::thread;
use std::time::{Duration, Instant};
use tokio::sync::Notify;

async fn delay(dur: Duration) {
    let when = Instant::now() + dur;
    let notify = Arc::new(Notify::new());
    let notify_clone = notify.clone();

    thread::spawn(move || {
        let now = Instant::now();

        if now < when {
            thread::sleep(when - now);
        }

        notify_clone.notify_one();
    });

    notify.notified().await;
}

#[tokio::main]
async fn main() {
    delay(Duration::from_secs(1)).await;
}

pin

还记得future trait上参数有个Pin<&mut Self>, 为什么要Pin future的引用?

来看下边一段代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
async fn my_async_fn() {
    // async logic here
}

#[tokio::main]
async fn main() {
    let mut future = my_async_fn();
    (&mut future).await;
    // error:
    // within `impl Future<Output = ()>`, the trait `Unpin` is not implemented for `[async fn body@src/main.rs:1:24: 3:2]`
}

当尝试执行一个异步函数的引用时,编译器会报错要求其是Unpin trait

为什么呢?

future本质是一个封装的状态机结构体,调度时会被移动,如果其包含引用,引用的地址要能保证生命周期至少在其完成前还存活,不然就会出现引用一个已失效的地址。

所以 Rust 引入了Unpin trait。这个Unpin是代表其不需要固定地址,可以安全引用。

常规的类型一般都是实现了的。对于未实现的!Unpin类型,一般可以将其Box::pin到堆上或用宏pin!到栈上来确保其地址在future移动期间是有效的。

代码如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use tokio::pin;

async fn my_async_fn() {
    // async logic here
}

#[tokio::main]
async fn main() {
    let future = my_async_fn();
    // option 1
    pin!(future);
    (&mut future).await;

    // option 2
    // let pinned_fut = Box::pin(future);
    // pinned_fut.await;
}

好了,今天就聊到这里,下一篇我们再聊聊多个异步同时怎么处理。

Pin感兴趣可以看看官方更详细的文档:Pinning[1]

异步编程更深入了解的话也推荐看下 tokio 的这篇:Async in depth[2]

参考资料

[1]

Pinning: https://rust-lang.github.io/async-book/04_pinning/01_chapter.html

[2]

Async in depth: https://tokio.rs/tokio/tutorial/async

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-01-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 菜鸟Miao 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
3分钟搞定下载微信视频号视频!无需第三方软件,亲测有效!
2020年是视频号的元年,现在2021视频号还处在发展初期,但是它的潜力是巨大的,将来的价值会超过抖音。
全栈程序员站长
2022/07/05
22.4K2
3分钟搞定下载微信视频号视频!无需第三方软件,亲测有效!
2023年最新最简单的微信视频号下载方法+工具
随着 5G 技术的发展,短视频越来越火~微信依靠数以十亿计的用户量推出视频号入局短视频,短视频江湖也从“南抖北快”进入群雄争霸的局面。
用户10294941
2023/03/02
24.1K0
​微信视频号下载器免费版下载 (微信视频号视频下载)
微信视频号下载器(微信视频号视频下载)重磅发布了,知识兔可以把微信的视频号里面的视频提取出来,知识兔适合广大的有需求的用户。知识兔主要提供微信视频号视频下载、知识兔直播流地址解析功能。
用户10122115
2022/11/05
4.3K2
微信视频号里的视频怎么下载到本地,两种方法可以帮你实现
不知道大家有没有看过微信的视频号,因为要做一个小视频,需要剪切多个视频合集,对方给我发来的部分视频源自微信视频号,结果我发现我下载不了,嗯嗯,因为在手机端没有下载也看不见网址,在PC端呢,无法右键也无法F12,总之看不到这个视频的原地址,当然因为没有下载地址,否则也不会写这篇文章了就。在网络找到几个办法,综合一下,目前我能实现的只有两种方法,好了说教程。
李洋博客
2022/04/06
49.3K3
微信视频号里的视频怎么下载到本地,两种方法可以帮你实现
如何微信公众号中的视频保存下来
在微信公众号中,我们常常会遇到一些有趣或有价值的视频内容,希望能够保存下来方便日后观看或分享。然而,由于微信本身的限制和版权保护等因素,要在微信中直接下载这些视频并不是一件容易的事情。在本文中,我们将探讨如何在遵守法律法规和版权保护的前提下,合法保存微信公众号中的视频内容,并提供一些实用的方法。
老虎也淘气
2024/01/30
2.6K0
如何微信公众号中的视频保存下来
搞定短视频!批量下载快手视频(附源码)
相信大家都接触了短视频平台,比如某音、某手等平台,竟然大家都熟悉了,那么今天辰哥分享的技术是:在某手上搜索视频,并实现下载!
Python研究者
2021/07/26
2.4K0
微信视频号下载器(微信视频号视频下载工具)
微信视频号下载器(微信视频号视频下载)重磅发布了,知识兔可以把微信的视频号里面的视频提取出来,适合广大的有需求的用户。主要提供微信视频号视频下载、知识兔直播流地址解析功能。
知识兔
2022/10/23
9.5K2
Frida爬虫分析流程——以微信视频号下载为例
微信的通信协议没有使用传统的https,而是采用 mmtls 和 quic 协议结合的方案(可能),导致常用的抓包方案完全无效。因此我们考虑使用逆向 hook 的方式,对微信视频号的数据进行获取。
mythsman
2022/11/14
11.2K2
Frida爬虫分析流程——以微信视频号下载为例
下载 m3u8 视频流
到现在,非常多的视频网站都是利用 m3u8 格式的特性,把一段视频分成多段,进而增加各类软件下载网页上视频的难度。
惶心
2018/06/19
21.1K3
下载 m3u8 视频流
YouTube 开始测试视频下载
由于 YouTube 不提供下载,所以你可以通过上百的站点,脚本,扩展和程序下载 YouTube 视频。最初,适合下载的格式是 FLV,这种格式只能使用 Adobe Flash 来播放。然后 YouTube 开始测试高清晰视频(包括 MP4),所以现在可以把 YouTube 视频导出成 MP4 格式。 其实下载 YouTube 导出的 MP4 文件,你可以使用以前下载 FLV 文件一样的 URL,然后在 URL 的最后附加上 "&fmt=18" 即可,如下:
Denis
2023/04/14
7670
YouTube 开始测试视频下载
腾讯出品!这个免费网盘小程序,让你快速「找私货」| 亲儿子 #17
在 2017 年 1 月 16 日前,腾讯微云为每个帐号分配了非常大的网盘容量,很多人都用它来当照片、文件等的「仓库」。
知晓君
2018/07/30
1.4K0
MediaGo:跨平台视频提取下载的开源神器
在数字化浪潮中,视频资源已成为知识获取与休闲娱乐的核心载体。然而当用户试图保存这些内容时,却常常陷入技术困局:抓包工具的复杂配置、TS流解析的晦涩操作,让非技术用户望而却步。而市面上多数下载工具更是暗藏套路——广告弹窗干扰、免费次数限制、会员订阅,都在消耗着用户体验。MediaGo 的横空出世,以零门槛视频自由为理念,通过开源免费的跨平台解决方案,重新定义了流媒体下载的边界。本文将从技术突破、场景适配到一键安装,全方位解密这款现象级开源利器。
修己xj
2025/03/12
4160
MediaGo:跨平台视频提取下载的开源神器
python爬虫公众号所有信息,并批量下载公众号视频
本篇添加一个批量下载公众号内视频的功能,可以实现完全复制一个公众号,危险动作,请不要操作!谢谢
Python疯子
2019/12/16
2.8K0
python爬虫公众号所有信息,并批量下载公众号视频
网页视频下载方法[通俗易懂]
有时候我们在做PPT或者撰写一些报告、案例的时候,需要一些视频作为素材,网上搜到后,想下载却比较麻烦,有的在专业视频网站上,有的在新闻网站上,有的在机构网站上,有的在社交媒体上,有没有简便、快速、可行的视频下载方法,并且不需要付费或者安装额外软件呢。下面说明几种方法,基本可以涵盖绝大多数情况。
全栈程序员站长
2022/07/23
6.7K0
AI自动下载视频网站页面的视频
很多视频网站,可以在线免费看,但是无法下载。一般情况下,网站视频播放是采用了m3u8技术。M3U8是一种基于HTTP Live Streaming (HLS) 协议的播放列表格式,广泛应用于在线视频播放,特别是在直播和点播场景中。让AI写一个下载程序,就可以下载大部分在线视频网站的视频到本地电脑中了。
AIGC部落
2025/02/18
1410
AI自动下载视频网站页面的视频
uniapp微信小程序完美实现下载视频功能
会提示错误 saveVideoToPhotosAlbum:fail invalid file type
iwhao
2024/06/19
8890
Pyhon爬虫,微信公众号文章视频下载爬虫工具源码助手
以前本渣渣分享过公众号文章内容(文字+图片采集),在这里本渣渣继续分享关于公众号文章内的视频内容采集获取下载方式,可能有不少大佬哥们有获取视频的需求,本渣渣搜集整理了相关内容资料,简单的做一些分享及总结,当然仅供参考和学习!
二爷
2022/03/29
2.6K1
Pyhon爬虫,微信公众号文章视频下载爬虫工具源码助手
Xilisoft YouTube Video Converter mac(视频下载和转换工具)中文版
Xilisoft YouTube Video Converter 作为一款功能强大的视频下载和转换工具,提供独特的“下载+转换”一步解决方案让您直接下载 YouTube 视频并将其转换为 AVI、MPEG、MP4、3GP、3G2、SWF、MP3等音视频格式。可以将您喜欢的 YouTube 视频直接保存到本地或转换为各种主流视频格式,还可以将本地的FLV视频转换为想要的视频格式。
Mac知识分享
2022/08/08
5110
2023版微信视频号无水印下载神器终于来了!轻松下载保存视频,超级简单
相信很多小伙伴平常都喜欢刷短视频,看到有趣的内容可能就想保存到本地,无论是分享给好友还是自己用作素材都是非常不错的选择。
用户10294941
2023/03/02
6.5K0
android微信聊天记录导出到电脑【微信安卓版技巧】
  微信,对它又爱又恨!爱的是微信能替代很多手机通话短信,恨的是有些较早前的手机不能友好支持,比如ytkah之前用的i8000,挺上手的,就是没办法装微信,当时工作需要必须用微信,只好忍痛割爱买了个android手机。安卓手机还算可以吧,就是流量大户、占用内存太大了,经常会生成一个很大相册预览图的文件夹,有时拍照就提示空间不足,得先清理一下。等你清理完,妹子的媚眼不懂飞向哪个大叔身上了,哎!   腾讯出招了:通过腾讯电脑管家将微信聊天记录备份到电脑上   如果不想安装电脑管家,可以试试下面的方法androi
ytkah
2018/03/05
5.4K0
android微信聊天记录导出到电脑【微信安卓版技巧】
推荐阅读
相关推荐
3分钟搞定下载微信视频号视频!无需第三方软件,亲测有效!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验