[async_std]--2.2--Tasks

Tasks

Now that we know what Futures are, we want to run them!
既然我们知道Futures 是什么,我们就要运行它们!

In async-std, the tasks module is responsible for this. The simplest way is using the block_on function:
在async_std中,tasks模块负责这一点。最简单的方法是使用block_on函数:

use async_std::{fs::File, io, prelude::*, task};

async fn read_file(path: &str) -> io::Result<String> {
    let mut file = File::open(path).await?;
    let mut contents = String::new();
    file.read_to_string(&mut contents).await?;
    Ok(contents)
}

fn main() {
    let reader_task = task::spawn(async {
        let result = read_file("data.csv").await;
        match result {
            Ok(s) => println!("{}", s),
            Err(e) => println!("Error reading file: {:?}", e)
        }
    });
    println!("Started task!");
    task::block_on(reader_task);
    println!("Stopped task!");
}

This asks the runtime baked into async_std to execute the code that reads a file. Let's go one by one, though, inside to outside.

这要求在async_std中嵌入运行时来执行读取文件的代码。让我们一个一个从里到外。

async {
    let result = read_file("data.csv").await;
    match result {
        Ok(s) => println!("{}", s),
        Err(e) => println!("Error reading file: {:?}", e)
    }
};

This is an async block. Async blocks are necessary to call async functions, and will instruct the compiler to include all the relevant instructions to do so. In Rust, all blocks return a value and async blocks happen to return a value of the kind Future.
这是一个异步块。异步块是调用异步函数所必需的,它将指示编译器包含所有相关的指令。在Rust中,所有块都返回一个值,而异步块恰好返回一个未来类型的值。

But let's get to the interesting part:
但让我们来看看有趣的部分:

task::spawn(async { });

spawn takes a Future and starts running it on a Task. It returns a JoinHandle. Futures in Rust are sometimes called cold Futures. You need something that starts running them. To run a Future, there may be some additional bookkeeping required, e.g. whether it's running or finished, where it is being placed in memory and what the current state is. This bookkeeping part is abstracted away in a Task.
spawn需要一个Future 并开始在一个任务上运行它。它返回一个JoinHandle。Rust 的Futures 有时被称为冻结的Futures。你需要一些东西来管理和运行他们。为了运行一个Future,可能需要一些额外的记录请求,例如它是运行的还是完成的,它放在内存中的位置以及当前的状态。这个记录部分是在一个任务中抽象出来的。

A Task is similar to a Thread, with some minor differences: it will be scheduled by the program instead of the operating system kernel, and if it encounters a point where it needs to wait, the program itself is responsible for waking it up again. We'll talk a little bit about that later. An async_std task can also have a name and an ID, just like a thread.
任务类似于线程,但有一些细微的区别:任务将由程序而不是操作系统内核调度,如果遇到需要等待的点,程序本身将负责再次唤醒它。我们稍后再谈。异步任务也可以有名称和ID,就像线程一样。

For now, it is enough to know that once you have spawned a task, it will continue running in the background. The JoinHandle is itself a future that will finish once the Task has run to conclusion. Much like with threads and the join function, we can now call block_on on the handle to block the program (or the calling thread, to be specific) and wait for it to finish.
现在,只要知道一旦生成了一个任务,它将继续在后台运行就足够了。JoinHandle本身就是一个future ,它将在任务运行到结束时完成。与线程和join函数非常相似,我们现在可以调用句柄上的block_on阻止程序(或调用线程,具体来说)并等待它完成。

Tasks in async_std

Tasks in async_std are one of the core abstractions. Much like Rust's threads, they provide some practical functionality over the raw concept. Tasks have a relationship to the runtime, but they are in themselves separate. async_std tasks have a number of desirable properties:
异步标准中的任务是核心抽象之一。就像Rust的线程一样,它们提供了一些超越原始概念的实用功能。任务与运行时有关系,但它们本身是独立的。异步任务具有许多理想的属性:

  • They are allocated in one single allocation //它们被分配到一个单独的分配中
  • All tasks have a backchannel, which allows them to propagate results and errors to the spawning task through the JoinHandle //所有任务都有一个backchannel,允许它们通过JoinHandle将结果和错误传播到生成任务
  • They carry useful metadata for debugging //它们为调试提供了有用的元数据
  • They support task local storage //它们支持任务本地存储

async_stds task API handles setup and teardown of a backing runtime for you and doesn't rely on a runtime being explicitly started.
async_stds task API为您处理后台运行时的设置和拆卸,而不依赖于显式启动的运行时。

Blocking

Tasks are assumed to run concurrently, potentially by sharing a thread of execution. This means that operations blocking an operating system thread, such as std::thread::sleep or io function from Rust's std library will stop execution of all tasks sharing this thread. Other libraries (such as database drivers) have similar behaviour. Note that blocking the current thread is not in and of itself bad behaviour, just something that does not mix well with the concurrent execution model of async-std. Essentially, never do this:
假定任务是并发运行的,可能是通过共享一个执行线程来实现的。这意味着阻塞操作系统线程的操作,例如std::thread::sleep或来自Rust的std库的io函数,将停止共享该线程的所有任务的执行。其他库(如数据库驱动程序)也有类似的行为。注意,阻塞当前线程本身并不是不好的行为,只是与async-std的并发执行模型不能很好地结合在一起。基本上,永远不要这样做:

fn main() {
    task::block_on(async {
        // this is std::fs, which blocks
        std::fs::read_to_string("test_file");
    })
}

If you want to mix operation kinds, consider putting such blocking operations on a separate thread.
如果希望混合操作类型,请考虑将此类阻塞操作放在单独的线程上.

Errors and panics

Tasks report errors through normal patterns: If they are fallible, their Output should be of kind Result<T,E>.
任务通过正常模式报告错误:如果它们是错误的,那么它们的输出应该是类 Result<T,E>。

In case of panic, behaviour differs depending on whether there's a reasonable part that addresses the panic. If not, the program aborts.
在 panic 的情况下,行为的不同取决于是否有一个合理的部分来解决panic。否则,程序将中止。

In practice, that means that block_on propagates panics to the blocking component:
实际上,这意味着block-on将 panics 传播到blocking组件:

fn main() {
    task::block_on(async {
        panic!("test");
    });
}
thread 'async-task-driver' panicked at 'test', examples/panic.rs:8:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

While panicing a spawned task will abort:
在 panicing, 生成任务将中止:

task::spawn(async {
    panic!("test");
});

task::block_on(async {
    task::sleep(Duration::from_millis(10000)).await;
})
thread 'async-task-driver' panicked at 'test', examples/panic.rs:8:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
Aborted (core dumped)
//线程'async task driver'在'test'时崩溃,examples/panic.rs:8:9
//注意:使用“RUST\u BACKTRACE=1”环境变量运行以显示回溯。
//中止(核心转储)

That might seem odd at first, but the other option would be to silently ignore panics in spawned tasks. The current behaviour can be changed by catching panics in the spawned task and reacting with custom behaviour. This gives users the choice of panic handling strategy.
一开始这可能看起来很奇怪,但另一个操作是默默地忽略spawned tasks中的 panics 。当前的行为可以通过捕获spawned tasks中的panics 并对自定义行为作出反应来改变。这为用户提供了panics 处理策略的选择。

Conclusion 结论

async_std comes with a useful Task type that works with an API similar to std::thread. It covers error and panic behaviour in a structured and defined way.
async_std附带了一个有用的任务类型,它与类似std::thread的API一起工作。它以结构化和明确的方式涵盖了error 和 panic 行为。

Tasks are separate concurrent units and sometimes they need to communicate. That's where Streams come in.
任务是独立的并发单元,有时它们需要通信。那是 Streams 流入的地方。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容

  • by Lene Nielsen The persona method has developed from bei...
    鲜核桃阅读 1,054评论 0 0
  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 9,448评论 0 13
  • Chapter 1 In the year 1878, I took my degree of Doctor of...
    foxgti阅读 3,667评论 0 6
  • 你总是,总是说我幼稚,哎哟喂,你好成熟哦,世界上没有人比你经历的更多了,没人比你更成熟了,别人说什么,你都会说,不...
    不该奢求阅读 233评论 0 0
  • 据说美国总统林肯从军时,他和队友经常被教练臭骂。有一次,有个队友被骂后很气愤,想写一封匿名信羞辱教练。林肯在一旁也...
    幼儿说阅读 956评论 0 8