鉴于以下简化程序:
#[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
之外,因此可能会与tag
的生命周期发生冲突。
我的目标是将所有当前逻辑放在线程内部的线程闭包中,因为这是我想要传播到多个线程的“处理”。我怎样才能实现这一目标,但仍然会向现有的tx
更长的时间发送一些价值?
我正在使用以下Rust版本:
$ rustc --version
rustc 1.9.0 (e4e8b6668 2016-05-18)
$ cargo --version
cargo 0.10.0-nightly (10ddd7d 2016-04-08)
答案 0 :(得分:3)
a_name
&str
来自tag
。因此,它的生命周期由tag
限定。将非'static
引用沿着通道发送到另一个线程是不安全的。它指的是线程堆栈上的东西,一旦接收器试图访问它就可能不再存在。
在您的情况下,您应该将a_name
提升为类型String
的拥有值,该值将移至接收方线程。
tx.send(a_name.to_owned()).unwrap();