为了确保不陷入XY问题,这是我正在尝试做的事情:
struct
和在伪锈中:
extern crate crossbeam;
struct Settings {
// ... many fields
}
fn main() {
crossbeam::scope(|scope| {
for score in 0..max_feasible_score {
scope.spawn(|_| {
let work_result = do_cool_computation(&settings, score);
println!(work_result);
}
}
}).unwrap();
}
现在无法编译。 Rust抱怨score
被借用到可能超过其外部功能的闭包中,并建议更改scope.spawn
闭包参数以转换为move || {...}
闭包。
但是,这将使&settings
无效,因为第一次循环迭代将在移动闭包中获得settings
的所有权。
[使其唯一可行的方法就是例如将Settings
结构复制到每个线程中(在我的实际应用中这是相当昂贵的),或在settings
周围引入一个圆弧,这也感到有点不幸。
我们有没有办法在这里规避引用计数?有没有一种方法可以将score
移入内部闭包,同时仍然允许引用settings
?
我在rayon::scope的文档中找到了一个答案,该答案恰好与以下问题有关:“ [从有作用域的线程范围内访问堆栈数据]”。该页面上还有一个示例,比该问题中的伪代码更清楚。
事实证明,您可以:-使用移动闭包,但在外部作用域中通过用引用将其阴影化来引用变量,因此使用let settings = &settings
:]通过引用而不是按值捕获它们
fn main() {
crossbeam::scope(|scope| {
let settings = &settings; // refer to outer variable by reference
for score in 0..max_feasible_score {
scope.spawn(move |_| {
let work_result = do_cool_computation(&settings, score);
println!(work_result);
}
}
}).unwrap();
}
let score = score
在闭包内隐藏所需变量,即可移动所需的变量:fn main() { crossbeam::scope(|scope| { for score in 0..max_feasible_score { scope.spawn(|_| { let score = score; // capture only score let work_result = do_cool_computation(&settings, score); println!(work_result); } } }).unwrap(); }
所以: