Spawning
スポーンを使用すると、新しい非同期タスクをバックグラウンドで実行できます。これにより、そのタスクの実行中も他のコードの実行を継続できます。
メインスレッドをブロックせずに接続を受け付けたい Web サーバーがあるとします。
これを実現するには、async_std::task::spawn 関数を使用して、接続を処理する新しいタスクを作成して実行できます。この関数は future を受け取り、JoinHandle を返します。これは、タスクが完了した後でその結果を待機するために使用できます。
use async_std::{task, net::TcpListener, net::TcpStream};
use futures::AsyncWriteExt;
async fn process_request(stream: &mut TcpStream) -> Result<(), std::io::Error>{
stream.write_all(b"HTTP/1.1 200 OK\r\n\r\n").await?;
stream.write_all(b"Hello World").await?;
Ok(())
}
async fn main() {
let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap();
loop {
// Accept a new connection
let (mut stream, _) = listener.accept().await.unwrap();
// Now process this request without blocking the main loop
task::spawn(async move {process_request(&mut stream).await});
}
}
spawn によって返される JoinHandle は Future トレイトを実装しているため、.await してタスクの結果を取得できます。
これにより、スポーンされたタスクが完了するまで現在のタスクはブロックされます。タスクを await しない場合、プログラムはそのタスクを待機せずに実行を継続し、タスクが完了する前に関数が完了した場合はそのタスクをキャンセルします。
#![allow(unused)]
fn main() {
use futures::future::join_all;
async fn task_spawner(){
let tasks = vec![
task::spawn(my_task(Duration::from_secs(1))),
task::spawn(my_task(Duration::from_secs(2))),
task::spawn(my_task(Duration::from_secs(3))),
];
// If we do not await these tasks and the function finishes, they will be dropped
join_all(tasks).await;
}
}
メインタスクとスポーンされたタスクの間で通信するには、使用している非同期ランタイムが提供するチャネルを使用できます。