45
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ついにstableになったRustのasync/awaitを試してみる

Last updated at Posted at 2019-11-08

:tada:祝!Rust 1.39.0

ついに、Rust 1.39.0になりました!そこで、既に他の方も書かれているかもしれないですが、安定化したasync/.awaitを試してみたいと思います(なお、筆者はRust及び非同期初心者です)。

基本的なasync/.await

最も基本的な使い方は、

async fn f() {
    let future = /* impl Futureな何か */;
    future.await;
}

です。簡単!と思ったのですが、.awaitasync関数またはブロックの中でしか呼べず、また.awaitをしないと実際には処理を開始してくれないので、(簡単には)asyncでないmain関数から呼び出せません...困った。

futures crateとの併用

futures 0.3を使えば簡単にasync/.awaitできるみたいなので、試してみました。

基本

まず、async fnで非同期処理したい関数を作成します(ここまではstdでできます。)

async fn long_task(task_id: usize) {
    println!("Task {} on {:?}", task_id, std::thread::current().id());
    std::thread::sleep(std::time::Duration::from_secs(1));
    println!("Task {} done", task_id);
}

追記: 今更ながらちゃんとドキュメントをみたら std::thread::sleepasync fn内では使ってはいけない と書いてありました。同様のことを行うには各runtime(tokioやasync_std、futuresの場合はfutures-timerというクレート)のDelayを使うとできるそうです。

続いてこれをmain関数から呼び出すわけですが、ここでfutures::executor::block_onを使います。

fn main() {
    let task = long_task(0); // ここではまだ実行されない
    futures::executor::block_on(task); // ここで実行される(.awaitの代わりのようなもの)
}

これで main関数と同じスレッドから long_task関数が呼び出せました。

別スレッドでの処理

非同期処理するからには異なるスレッドで実行したいので、それを試してみます。そのためにまずfuturesthread-pool featureを加えて、futures::executor::ThreadPoolを作ります。ビルダーから作っても良いですし、単にnewするだけでも大丈夫です。
別スレッドで処理してもらうためにspawn系を呼び出すのですが、単にspawnしてそのまま終わってしまうとやはり実行されない(ことがある)ので、後でjoinするために今回はspawn_with_handleを用いました。その結果、以下のような感じになりました。

use futures::{
    executor::{block_on, ThreadPool},
    future,
    task::SpawnExt,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut pool = ThreadPool::new()?;
    let mut futures = Vec::new();
    for i in 0..20 {
        futures.push(pool.spawn_with_handle(long_task(i))?);
    }
    block_on(future::join_all(futures));
    Ok(())
}

感想

現状、stdだけだと非同期処理を書くのはちょっと大変そうです。もちろん、futures crateもRustで書かれているので頑張れば以上のことをstdだけでできるはずですが、ソースコード見ても私にはなかなか難しそうだったので、素直に外部crateを使うことにします。ありがたや~

45
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?