问题
I'm spawning a thread that does some work. Sometimes I want this thread to die after the work is finished, other times I want it to wait for more work to do. To do this I pass in an Option<Receiver<T>>
. If Option<Receiver<T>>
is None
the thread should die, else it should wait to receive more work.
fn foo(rx: Option<Receiver<usize>>) {
thread::spawn(move || {
loop {
do_some_work();
if let Some(r) = rx {
match r.recv() {
Ok(x) => {}
Err(_) => panic!("Oh no!"),
}
} else {
break; //Die
}
}
});
}
(link to playground)
The compiler says:
error[E0382]: use of moved value
--> src/lib.rs:10:25
|
10 | if let Some(r) = rx {
| ^ value moved here, in previous iteration of loop
|
= note: move occurs because value has type `std::sync::mpsc::Receiver<usize>`, which does not implement the `Copy` trait
However if the Receiver
is not enclosed in an Option
everything is fine.
fn foo(rx: Receiver<usize>) {
thread::spawn(move || {
loop {
do_some_work();
match rx.recv() {
Ok(x) => {}
Err(_) => panic!("Oh no!"),
}
}
});
}
回答1:
When you write if let Some(r) = rx
, you consume rx
, making it unavailable for later.
You can use as_ref()
to get a reference to the inner object instead, leaving rx
usable:
fn foo(rx: Option<Receiver<usize>>) {
thread::spawn(move || {
loop {
do_some_work();
if let Some(r) = rx.as_ref() {
match r.recv() {
Ok(x) => {}
Err(_) => panic!("Oh no!"),
}
} else {
break; //Die
}
}
});
}
(link to playground)
来源:https://stackoverflow.com/questions/54993331/optionreceiver-moved-in-previous-loop-iteration