我有一個像這樣的簡單代碼來模擬異步代碼如何處理阻塞操作。
我期待所有這些“你好”列印將在 1000 毫秒后顯示。
但是這段代碼就像一個普通的阻塞代碼,每個 hello_wait 呼叫等待 1000 毫秒,并在 1000 毫秒后列印另一個 Hello。
我怎樣才能讓它同時運行?
use std::{time::Duration};
use async_std::task;
async fn hello_wait(){
task::sleep(Duration::from_millis(1000)).await;
println!("Hello");
}
#[async_std::main]
async fn main() {
hello_wait().await;
hello_wait().await;
hello_wait().await;
hello_wait().await;
hello_wait().await;
}
這是正在發生的事情:
// -- Wait 1000ms --
Hello
// -- Wait 1000ms --
Hello
// -- Wait 1000ms --
Hello
// -- Wait 1000ms --
Hello
// -- Wait 1000ms --
Hello
這就是我想要的:
// -- Wait 1000ms --
Hello
Hello
Hello
Hello
Hello
uj5u.com熱心網友回復:
我怎樣才能讓它同時運行?
您可以:
- 產生一個任務,這將使每個任務
hello_wait獨立調度 - 或“合并”期貨,這將同時并行驅動所有期貨
您的期望可能來自 Javascript 或 C# 異步,其中“基本”等待是一個task。任務是“活動的”,一旦你創建它們,它們就可以被調度并同時做它們的事情。
但是 rust 的核心 awaitable 更像是一個協程,所以它是惰性的(/被動):創建一個并沒有真正做任何事情,期貨必須被輪詢才能進展,并且在恢復之前await會反復輪詢直到完成。所以當你await做某事時,它完全運行,沒有機會在那個時候交錯。
因此,同時運行期貨需要兩件事之一:
- 他們升級到一個任務,這意味著他們可以自己安排,那是什么
spawn呢 - 或者將期貨組合成一個“元未來”,它可以在輪詢時輪詢它們,這就是構造喜歡
join_all或tokio::join做的事情
請注意,組合期貨不允許并行,因為期貨是“兄弟”,它們只能連續輪詢(因此實際上做事情),只是這種輪詢(以及進度)是交錯的。
生成任務確實允許并行(如果運行時是多執行緒的并且機器有多個內核——盡管后者現在非常普遍),但在生命周期和記憶體管理方面有其自身的局限性,并且成本更高.
這是各種選項的游樂場演示。它使用 tokio 因為顯然操場沒有 async_std,而且我不確定無論如何是否可以啟用“不穩定”功能,但除此之外,使用tokio::join(async_std's Future::joincan only join 2 future at a async_std's can only join 2 futures at a時間,所以你必須鏈接呼叫)它在 async_std 中的作業方式應該大致相同。
uj5u.com熱心網友回復:
我能夠用futurescrate以這種方式做到這一點join_all:
use std::time::Duration;
use async_std::task;
use futures::future;
async fn hello_wait(){
task::sleep(Duration::from_millis(1000)).await;
println!("Hello");
}
#[async_std::main]
async fn main() {
let mut asyncfuncs = vec![];
asyncfuncs.push(hello_wait());
asyncfuncs.push(hello_wait());
asyncfuncs.push(hello_wait());
asyncfuncs.push(hello_wait());
asyncfuncs.push(hello_wait());
future::join_all(asyncfuncs.into_iter()).await;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/360663.html
標籤:异步 锈 rust-async-std
上一篇:將模板傳遞給異步函式
