延长线程变量的生命周期

时间:2015-05-19 16:04:57

标签: multithreading rust lifetime

我正在从文件中读取一个字符串,将它按行分成一个向量,然后我想在单独的线程中对提取的行进行一些操作。像这样:

use std::fs::File;
use std::io::prelude::*;
use std::thread;
fn main() {
    match File::open("data") {
        Ok(mut result) => {
            let mut s = String::new();
            result.read_to_string(&mut s);
            let k : Vec<_> = s.split("\n").collect();
            for line in k {
                thread::spawn(move || {
                    println!("nL: {:?}", line);
                });
            }

        }
        Err(err) => {
            println!("Error {:?}",err);
        }
    }
}

当然这会引发错误,因为s会在线程启动之前超出范围:

s` does not live long enough
main.rs:9           let k : Vec<_> = s.split("\n").collect();
                                     ^

我现在能做什么?我尝试了许多内容,例如BoxArc,但我无法使其发挥作用。我不知何故需要创建一个s的副本,它也存在于线程中。但是我该怎么做?

1 个答案:

答案 0 :(得分:4)

从根本上说,问题在于lines的借用切片。这里真的没有什么可以做的,因为无法保证每个line都不会比s本身更长。

另外,要明确一点:Rust中绝对没有办法“延长变量的生命周期”。它根本无法完成。

最简单的方法是从line 借用转到拥有。像这样:

use std::thread;
fn main() {
    let mut s: String = "One\nTwo\nThree\n".into();
    let k : Vec<String> = s.split("\n").map(|s| s.into()).collect();
    for line in k {
        thread::spawn(move || {
            println!("nL: {:?}", line);
        });
    }
}

.map(|s| s.into())&str转换为String。由于String拥有其内容,因此可以安全地将其移动到每个线程的闭包中,并且将独立于创建它的线程生存。

注意 可以使用新的作用域线程API在每晚Rust中执行此操作,但这仍然不稳定。