use std::sync::Arc;

use tokio::sync::mpsc;

async fn student(id : i32,tx : Arc<mpsc::Sender<String>>) {
    println!("student {} is getting their hw.",id);
    tx.send(format!("student {}'s hw !",id)).await.unwrap();
}

async fn teacher(mut rc : mpsc::Receiver<String>) -> Vec<String> {
    let mut homeworks = Vec::new();
    while let Some(hw) = rc.recv().await {
        println!("{hw}");
        homeworks.push(hw);
    }
    homeworks
}

#[tokio::main]
async fn main() {
    let (tx,rc): (mpsc::Sender<String>, mpsc::Receiver<String>) = mpsc::channel(100);
    let ch_arc: Arc<mpsc::Sender<String>> = Arc::new(tx);
    
    for i in 0..10 {
        tokio::task::spawn(student(i,ch_arc.clone()));
    }
    let hws = teacher(rc).await;
    println!("{:?}",hws);
}

我目前正在学习Rust中的通道,现在我遇到了一些问题.问题是当我运行 teacher(rc).await线时,
代码在这一点上卡住了,我不知道为什么会发生这种情况,但我在解决这个问题时观察到的一件事是,当我产生多个任务时,我会陷入循环,但当我只在student(i,ch_arc.clone());行做一个spawn时,它工作得很好. 有人能帮我吗?

推荐答案

看看这里的这个循环:

while let Some(hw) = rc.recv().await {

recv只会在丢弃发送方、挂断通道时返回None.发送者在AN Arc中,因此当所有Arc都被丢弃时,它将被丢弃.

student期货中有10个Arc,当每一个Arc结束时,它们都会被抛出.他们没有什么可以等待的,所以这种情况发生得很快.然而,还剩下Arc美元.直到main结束时,ch_arc才被丢弃,这发生在呼叫teacher之后.因此,ch_arc永远不会被丢弃.

您可以通过手动删除ch_arc来修复此问题:

#[tokio::main]
async fn main() {
    let (tx, rc): (mpsc::Sender<String>, mpsc::Receiver<String>) = mpsc::channel(100);
    let ch_arc: Arc<mpsc::Sender<String>> = Arc::new(tx);

    for i in 0..10 {
        tokio::task::spawn(student(i, ch_arc.clone()));
    }

    drop(ch_arc);

    let hws = teacher(rc).await;
    println!("{:?}", hws);
}

或者把ch_arc块钱放进一个街区.此块返回rc,因为您稍后需要使用rc.

#[tokio::main]
async fn main() {
    let rc = {
        let (tx, rc): (mpsc::Sender<String>, mpsc::Receiver<String>) = mpsc::channel(100);
        let ch_arc: Arc<mpsc::Sender<String>> = Arc::new(tx);

        for i in 0..10 {
            tokio::task::spawn(student(i, ch_arc.clone()));
        }
        rc
    };

    let hws = teacher(rc).await;
    println!("{:?}", hws);
}

Rust相关问答推荐

为什么我的梅森素数代码的指数越大,速度就越快?

rust 迹-内存管理-POP所有权-链表

像这样的铁 rust 图案除了‘选项’之外,还有其他 Select 吗?

Rust&;Tokio:如何处理更多的信号,而不仅仅是SIGINT,即SIGQUE?

如何正确重新排列代码以绕过铁 rust 借入判断器?

有没有可能让泛型Rust T总是堆分配的?

在生存期内将非静态可变引用转换为范围内的静态可变引用

写入引用会更新基础值,但引用会打印意外的值

如何使用Actix Web for Rust高效地为大文件服务

为什么我需要 to_string 函数的参考?

Rust 中指向自身的引用如何工作?

使用在功能标志后面导入的类型,即使未启用功能标志

如何使用泛型满足 tokio 异步任务中的生命周期界限

切片不能被 `usize` 索引?

我的 Axum 处理程序无法编译:未实现 IntoResponse 特征

匹配结果时的简洁日志(log)记录

如何重写这个通用参数?

在 Rust 中组合特征的不同方法是否等效?

为什么当borrow 变量发生变化时,borrow 变量不会改变?

这个 match 语句的默认值应该是什么,还有一种方法可以解开 Some case (chess in rust)