无法在线程之间发送 &str,因为它的生存时间不够长



给定以下简化程序:

#[macro_use] extern crate log;
extern crate ansi_term;
extern crate fern;
extern crate time;
extern crate threadpool;
extern crate id3;
mod logging;
use std::process::{exit, };
use ansi_term::Colour::{Yellow, Green};
use threadpool::ThreadPool;
use std::sync::mpsc::channel;
use std::path::{Path};
use id3::Tag;
fn main() {
    logging::setup_logging();
    let n_jobs = 2;
    let files = vec!(
        "/tmp/The Dynamics - Version Excursions/01-13- Move on Up.mp3",
        "/tmp/The Dynamics - Version Excursions/01-09- Whole Lotta Love.mp3",
        "/tmp/The Dynamics - Version Excursions/01-10- Feel Like Making Love.mp3"
    );
    let pool = ThreadPool::new(n_jobs);
    let (tx, rx) = channel();
    let mut counter = 0;
    for file_ in files {
        let file_ = Path::new(file_);
        counter = counter + 1;
        let tx = tx.clone();
        pool.execute(move || {
            debug!("sending {} from thread", Yellow.paint(counter.to_string()));
            let tag = Tag::read_from_path(file_).unwrap();
            let a_name = tag.artist().unwrap();
            debug!("recursed file from: {} {}",
                   Green.paint(a_name), file_.display());
            tx.send(".").unwrap();
            // TODO amb: not working..
            // tx.send(a_name).unwrap();
        });
    }
    for value in rx.iter().take(counter) {
        debug!("receiving {} from thread", Green.paint(value));
    }
    exit(0);
}

一切都如预期的那样工作,除非将注释行(tx.send(a_name).unwrap();)放回去。在这种情况下,我得到以下错误:

error: `tag` does not live long enough
            let a_name = tag.artist().unwrap();
                         ^~~
    note: reference must be valid for the static lifetime...
note: ...but borrowed value is only valid for the block suffix following statement 1 at 39:58
            let tag = Tag::read_from_path(file_).unwrap();
            let a_name = tag.artist().unwrap();
            debug!("recursed file from: {} {}",
                   Green.paint(a_name), file_.display());
...

一般来说,我理解编译器告诉我什么,但我不认为有问题,因为变量tag是在闭包块内部定义的。我能猜到的唯一问题是,变量tx是外部的clone d,因此可能与tag的生命周期发生冲突。

我的目标是把线程闭包中的所有当前逻辑放在线程内部,因为这是我想要扩展到多个线程的"处理"。我怎样才能做到这一点,但仍然发送一些值到较长的现有tx ?

我使用以下Rust版本:

$ rustc --version
rustc 1.9.0 (e4e8b6668 2016-05-18)
$ cargo --version
cargo 0.10.0-nightly (10ddd7d 2016-04-08)

a_name是从tag借来的&str。因此,它的生命周期由tag限定。将非'static引用从通道发送到另一个线程是不安全的。它指的是线程堆栈上的一些东西,一旦接收方试图访问它,这些东西甚至可能不再存在。在您的示例中,您应该将a_name提升为类型为String的私有值,该值将被移动到接收线程。

tx.send(a_name.to_owned()).unwrap();

相关内容

最新更新