在Rust中传递到线程内的消息通道时的变量生存期问题

kq0g1dla  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(96)

我正在编写一个Rust程序,它可以执行以下操作:
1.创建一个线程数组来生成,每个线程都包含一个变量,该变量存储目录的路径:

let (tx, rx) = mpsc::channel();
let handles: Vec<_> = dir_list
        .into_iter()
        .map(|dir_path| {
            let path2 = dir_path.clone();
            let txc = tx.clone();
            thread::spawn(move || func(txc, &Path::new(&path2)))
        })
        .collect();
for h in handles {
        let _ = h.join();
    }

字符串
1.在func()中,运行一个for循环(在每个线程上),该循环使用walkdir crate(https://crates.io/crates/walkdir)遍历所述路径,并通过tx向接收者发送相应的消息:

for entry in WalkDir::new(&path) {
        if entry.is_err() {
            tx.send(Err((entry.unwrap_err(), 0)).unwrap());
            continue;
        }
        let entry = entry.unwrap(); // !
        match func2(&entry) {
            Ok(len) => {
                tx.send((entry.file_name(), Ok(len))).unwrap(); // !
            }
            Err(e) => {
                if e != SubDirError { // a custom error
                    tx.send((entry.file_name(), Err(e.into()))).unwrap(); // !
                }
            }
        }
    }
    drop(tx);


编译器抱怨entry.file_name()的生存期问题。似乎这个错误意味着它应该存在于整个函数中,这是不可能的,因为不同的目录路径使用了for循环:

error[E0597]: `entry` does not live long enough
  --> src/dir.rs:40:26
   |
24 | [<function header, redacted for clarity>]
   |                                    - let's call the lifetime of this reference `'1`
...
35 |         let entry = entry.unwrap();
   |             ----- binding `entry` declared here
...
40 |                 tx.send((entry.file_name(), Ok(len))).unwrap();
   |                 ---------^^^^^^^^^^^^^^^^^-----------
   |                 |        |
   |                 |        borrowed value does not live long enough
   |                 argument requires that `entry` is borrowed for `'1`
...
53 | }
   | - `entry` dropped here while still borrowed


我该怎么办?如果由于消息和线程的所有权问题而无法解决这个问题,我应该尝试其他什么替代方案?我需要在每次迭代时将entry.file_name()传递给通道。

xiozqbni

xiozqbni1#

通过将.to_os_string()附加到entry.file_name()来解决;即,将其从&OsStr升级到OsString。事实证明,您应该在通道中发送拥有的类型而不是借用的引用,因为Sender的生存期取决于类型(?).

相关问题