无法在线程之间发送 &str,因为它的寿命不够长
Unable to send a &str between threads because it does not live long enough
给定以下简化程序:
#[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
的生命周期发生冲突。
我的目标是把当前所有的逻辑都放在thread-closure里面的线程里面,因为这是"processing"我想分散到多个线程。我怎样才能做到这一点,但仍然向现有的时间较长的 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
是 &str
从 tag
借来的。因此,它的生命周期受限于 tag
。将非 'static
引用沿通道发送到另一个线程是不安全的。它指的是线程堆栈上的某些东西,一旦接收者尝试访问它,它甚至可能不再存在。
在您的情况下,您应该将 a_name
提升为 String
类型的自有值,该值将被移动到接收方线程。
tx.send(a_name.to_owned()).unwrap();
给定以下简化程序:
#[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
的生命周期发生冲突。
我的目标是把当前所有的逻辑都放在thread-closure里面的线程里面,因为这是"processing"我想分散到多个线程。我怎样才能做到这一点,但仍然向现有的时间较长的 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
是 &str
从 tag
借来的。因此,它的生命周期受限于 tag
。将非 'static
引用沿通道发送到另一个线程是不安全的。它指的是线程堆栈上的某些东西,一旦接收者尝试访问它,它甚至可能不再存在。
在您的情况下,您应该将 a_name
提升为 String
类型的自有值,该值将被移动到接收方线程。
tx.send(a_name.to_owned()).unwrap();