我是Ruust异步编程的初学者.我正在编写一个程序来实现睡眠排序算法,该算法可以对非负数组进行排序.其实现原理是,对于数组中的每个元素,在输出之前等待一段时间,等待时间与元素的值成正比.这样,一段时间后,数组将按从小到大的顺序输出.

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);
    }
}

该程序会打印正确的答案,但不会停止.我不知道为什么以及如何解决这个问题.

推荐答案

recv documentation(重点是我的):

如果通道已关闭并且通道的缓冲区中没有剩余的消息,则此方法返回None.[...]The channel is closed when all senders have been dropped, or when 101 is called.

因此,要停止接收,您需要在接收之前丢弃仍保留在main中的额外发件人:

// -- snip --

std::mem::drop(tx);
while let Some(i) = rx.recv().await {
    println!("{}", i);
}

或者拨打rx.close().但是,这将导致发件人try 在之后发送消息失败,从而中断您的Hibernate 排序实现.因此,在这种情况下,您只需删除额外的发件人即可.

Rust相关问答推荐

如果A == B,则将Rc A下推到Rc B

文档示例需要导入相关的 struct ,但仅在运行测试时.这是故意的行为吗?

如何在Tauri中将变量从后端传递到前端

有没有办法避免在While循环中多次borrow `*分支`

在Rust中是否可以使用Rc自动化约束传播

有没有一种惯用的方法来判断VEC中是否存在变体?

在复制类型中使用std::ptr::WRITE_VILAR进行内部可变性的安全性(即没有UnSafeCell)

为什么&;mut buf[0..buf.len()]会触发一个可变/不可变的borrow 错误?

在 Rust 中用问号传播错误时对类型转换的困惑?

tokio::sync::broadcast::Receiver 不是克隆

Nom 解析器无法消耗无效输入

将 &str 或 String 保存在变量中

返回优化后的标题:返回异步块的闭包的类型擦除

pyO3 和 Panics

返回迭代器的特征

在 Rust 中,为什么整数溢出有时会导致编译错误或运行时错误?

发生移动是因为 `data` 的类型为 `Vec`,它没有实现 `Copy` 特性

使用 rust-sqlx/tokio 时如何取消长时间运行的查询

通用类型,不同于输入类型,作为函数的返回值

需要括号的宏调用中的不必要的括号警告 - 这是编写宏的糟糕方法吗?