Published on

🦀 Rust 多线程通道 sync::mpsc::channel 报错:RecvError

Authors
  • avatar
    Name
    阿森 Hansen
    Twitter

问题

这次遇到的报错信息 panic 是:

Compiling playground v0.0.1 (/playground)
  Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.58s
    Running `target/debug/playground`
thread 'main' panicked at src/main.rs:7:23:
called `Result::unwrap()` on an `Err` value: RecvError
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

示例代码:

use std::sync::mpsc;

fn main() {
    let rx = create_channel();
    // 侦听 rx 接收端通道,在这一步 panic
    let data = rx.recv().unwrap();
    println!("{:?}", data);
}

fn create_channel() -> mpsc::Receiver<u16> {
    let (tx, rx) = mpsc::channel::<u16>();
    return rx;
}

分析

这个问题一般是在使用 std::sync::mpsc::channel 遇到的错误。当发送端 tx 已经被销毁,但是 rx 仍然在被使用的情况下会出现。

解决 1

在 main 内部创建 channel。

use std::sync::mpsc;

fn main() {
    // 在 main 函数创建 channel
    let (tx, rx) = mpsc::channel::<u16>();
    // 侦听,这里就不会 panic,而会阻塞,因为 tx 没有发送信息
    let data = rx.recv().unwrap();
    println!("{:?}", data);
}

解决 2

create_channel 函数中将 tx 也同时返回

use std::sync::mpsc;

fn main() {
    let (tx, rx)= create_channel();
    let data = rx.recv().unwrap();
    println!("{:?}", data);
}

fn create_channel() -> (mpsc::Sender<u16>, mpsc::Receiver<u16>) {
    let (tx, rx) = mpsc::channel::<u16>();
    // 同时返回 tx, rx
    return (tx, rx);
}

总结:通道的生命周期

因为 Rust 有生命周期机制。如果 txcreate_channel() 中不返回,那么会在函数执行后销毁。rx 变为孤儿,通道状态变为关闭,然后报错。

如果将 tx 返回,那么它的所有权交给 main()tx 依然存活,同时 rx 仍然是有效状态,程序正常执行。

我好喜欢,理性而又严谨的 Rust !😁