简体   繁体   English

延长线程变量的生命周期

[英]Extend lifetime of a variable for thread

I am reading a string from a file, splitting it by lines into a vector and then I want to do something with the extracted lines in separate threads. 我正在从文件中读取字符串,将其按行拆分为向量,然后要对提取的行在单独的线程中进行某些处理。 Like this: 像这样:

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);
        }
    }
}

Of course this throws an error, because s will go out of scope before the threads are started: 当然,这会引发错误,因为s在启动线程之前将超出范围:

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

What can I do now? 我现在能做什么? I've tried many things like Box or Arc , but I couldn't get it working. 我已经尝试了很多类似BoxArc ,但是我无法使其正常工作。 I somehow need to create a copy of s which also lives in the threads. 我不知何故需要创建s的副本,该副本也存在于线程中。 But how do I do that? 但是我该怎么做呢?

The problem, fundamentally, is that line is a borrowed slice into s . 从根本上讲,问题是那条lines的借来切片。 There's really nothing you can do here, since there's no way to guarantee that each line will not outlive s itself. 没什么好说的,你可以在这里做,因为没有办法保证每个line不会活得比s本身。

Also, just to be clear: there is absolutely no way in Rust to "extend the lifetime of a variable". 同样,要明确一点:Rust中绝对没有 “延长变量的生存期”的方法。 It simply cannot be done. 这根本无法完成。

The simplest way around this is to go from line being borrowed to owned . 解决这个问题的最简单的方法是从走line借用拥有 Like so: 像这样:

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);
        });
    }
}

The .map(|s| s.into()) converts from &str to String . .map(|s| s.into())&str转换为String Since a String owns its contents, it can be safely moved into each thread's closure, and will live independently of the thread that created it. 由于String拥有其内容,因此可以安全地将其移动到每个线程的闭包中,并且独立于创建它的线程而存在。

Note : you could do this in nightly Rust using the new scoped thread API, but that is still unstable. 注意 :您可以在每晚的Rust中使用新的作用域线程API进行此操作,但这仍然不稳定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM