我是 rust 異步編程的初學者。我正在撰寫一個程式來實作睡眠排序演算法,它可以對非負陣列進行排序。它的實作原理是對陣列中的每一個元素,等待一段時間再輸出,等待時間與元素的值成正比。這樣,經過一段時間后,陣列就會按照從小到大的順序輸出。
use std::time::Duration;
use text_io::read;
use tokio::sync::mpsc::channel;
#[tokio::main]
async fn main() {
let n: u32 = read!();
let (tx, mut rx) = channel::<u32>(n as usize);
let mut before: Vec<u32> = Vec::new();
for _ in 0..n {
let a = read!();
before.push(a);
}
for i in before.into_iter() {
let tx = tx.clone();
tokio::spawn(async move {
tokio::time::sleep(Duration::from_millis((50 * i) as u64)).await;
if let Err(_) = tx.send(i).await {
panic!();
}
});
}
while let Some(i) = rx.recv().await {
println!("{}", i);
}
}
這個程式列印出正確的答案,但它不會停止。我不知道為什么以及如何解決它。
uj5u.com熱心網友回復:
從recv檔案(強調我的):
None如果通道已關閉并且通道緩沖區中沒有剩余訊息,則此方法回傳。[...]當所有發送者都被丟棄或被close呼叫時,通道將關閉。
因此,要停止接收,您需要在接收之前洗掉您仍然保留的額外發件人main:
// -- snip --
std::mem::drop(tx);
while let Some(i) = rx.recv().await {
println!("{}", i);
}
否則打電話rx.close()。但是,這將導致發送者在之后嘗試發送訊息失敗,從而破壞您的睡眠排序實作。因此,在這種情況下,您只需洗掉額外的發件人即可。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/508487.html
