【发布时间】:2021-03-24 06:31:45
【问题描述】:
我已阅读以下问题:
并详细阐述了一些更复杂的测试。 以下代码为函数添加了一个 &str 参数,它可以工作:
use std::{
thread,
time::{Duration, Instant},
};
fn main() {
let scheduler = thread::spawn(|| {
let wait_time = Duration::from_millis(500);
let one: &str = "Alpha";
let two: &str = "Beta";
// Make this an infinite loop
// Or some control path to exit the loop
for _ in 0..5 {
let start = Instant::now();
eprintln!("Scheduler starting at {:?}", start);
let thread_a = thread::spawn(move || { a(&one) });
let thread_b = thread::spawn(move || { b(&two) });
thread_a.join().expect("Thread A panicked");
thread_b.join().expect("Thread B panicked");
let runtime = start.elapsed();
if let Some(remaining) = wait_time.checked_sub(runtime) {
eprintln!(
"schedule slice has time left over; sleeping for {:?}",
remaining
);
thread::sleep(remaining);
}
}
});
scheduler.join().expect("Scheduler panicked");
}
fn a(a: &str) {
eprintln!("{}", a);
thread::sleep(Duration::from_millis(100))
}
fn b(b: &str) {
eprintln!("{}", b);
thread::sleep(Duration::from_millis(200))
}
我的理解是这行得通,因为 Copy Trait 是为 str 实现的。 现在考虑以下示例:
use std::{
thread,
time::{Duration, Instant},
};
fn main() {
let scheduler = thread::spawn(|| {
let wait_time = Duration::from_millis(500);
let one: String = String::from("Alpha");
let two: String = String::from("Beta");
// Make this an infinite loop
// Or some control path to exit the loop
for _ in 0..5 {
let start = Instant::now();
eprintln!("Scheduler starting at {:?}", start);
let thread_a = thread::spawn(move || { a(&one) });
let thread_b = thread::spawn(move || { b(&two) });
thread_a.join().expect("Thread A panicked");
thread_b.join().expect("Thread B panicked");
let runtime = start.elapsed();
if let Some(remaining) = wait_time.checked_sub(runtime) {
eprintln!(
"schedule slice has time left over; sleeping for {:?}",
remaining
);
thread::sleep(remaining);
}
}
});
scheduler.join().expect("Scheduler panicked");
}
fn a(a: &str) {
eprintln!("{}", a);
thread::sleep(Duration::from_millis(100))
}
fn b(b: &str) {
eprintln!("{}", b);
thread::sleep(Duration::from_millis(200))
}
我在编译时得到这个:
error[E0382]: use of moved value: `one`
--> src\main.rs:19:42
|
10 | let one: String = String::from("Alpha");
| --- move occurs because `one` has type `String`, which does not implement the `Copy` trait
...
19 | let thread_a = thread::spawn(move || { a(&one) });
| ^^^^^^^ --- use occurs due to use in closure
| |
| value moved into closure here, in previous iteration of loop
error[E0382]: use of moved value: `two`
--> src\main.rs:20:42
|
11 | let two: String = String::from("Beta");
| --- move occurs because `two` has type `String`, which does not implement the `Copy` trait
...
20 | let thread_b = thread::spawn(move || { b(&two) });
| ^^^^^^^ --- use occurs due to use in closure
| |
| value moved into closure here, in previous iteration of loop
error: aborting due to 2 previous errors
EDIT1
似乎可以使用 .clone() 解决 但现在考虑以下代码:
use std::{
thread,
time::{Duration, Instant},
};
fn main() {
let one: String = String::from("Alpha");
let two: String = String::from("Beta");
let scheduler = thread::spawn(|| {
let wait_time = Duration::from_millis(500);
// Make this an infinite loop
// Or some control path to exit the loop
for _ in 0..5 {
let start = Instant::now();
eprintln!("Scheduler starting at {:?}", start);
let one = one.clone();
let two = two.clone();
let thread_a = thread::spawn(move || { a(&one) });
let thread_b = thread::spawn(move || { b(&two) });
thread_a.join().expect("Thread A panicked");
thread_b.join().expect("Thread B panicked");
let runtime = start.elapsed();
if let Some(remaining) = wait_time.checked_sub(runtime) {
eprintln!(
"schedule slice has time left over; sleeping for {:?}",
remaining
);
thread::sleep(remaining);
}
}
});
scheduler.join().expect("Scheduler panicked");
}
fn a(a: &str) {
eprintln!("{}", a);
thread::sleep(Duration::from_millis(100))
}
fn b(b: &str) {
eprintln!("{}", b);
thread::sleep(Duration::from_millis(200))
}
我现在收到不同的错误代码:
error[E0373]: closure may outlive the current function, but it borrows `two`, which is owned by the current function
--> src\main.rs:11:35
|
11 | let scheduler = thread::spawn(|| {
| ^^ may outlive borrowed value `two`
...
21 | let two = two.clone();
| --- `two` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src\main.rs:11:21
|
11 | let scheduler = thread::spawn(|| {
| _____________________^
12 | | let wait_time = Duration::from_millis(500);
13 | |
14 | | // Make this an infinite loop
... |
38 | | }
39 | | });
| |______^
help: to force the closure to take ownership of `two` (and any other referenced variables), use the `move` keyword
|
11 | let scheduler = thread::spawn(move || {
| ^^^^^^^
error[E0373]: closure may outlive the current function, but it borrows `one`, which is owned by the current function
--> src\main.rs:11:35
|
11 | let scheduler = thread::spawn(|| {
| ^^ may outlive borrowed value `one`
...
20 | let one = one.clone();
| --- `one` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src\main.rs:11:21
|
11 | let scheduler = thread::spawn(|| {
| _____________________^
12 | | let wait_time = Duration::from_millis(500);
13 | |
14 | | // Make this an infinite loop
... |
38 | | }
39 | | });
| |______^
help: to force the closure to take ownership of `one` (and any other referenced variables), use the `move` keyword
|
11 | let scheduler = thread::spawn(move || {
| ^^^^^^^
error: aborting due to 2 previous errorsù
【问题讨论】:
标签: multithreading rust closures borrowing