挂在 Rust 中的通道接收器迭代器中?
Hanging in channel receiver iterator in Rust?
以下代码在迭代器中挂起:(playground)
#![allow(unused)]
fn main() {
use std::sync::mpsc::channel;
use std::thread;
let (send, recv) = channel();
let num_threads = 3;
for i in 0..num_threads {
let thread_send = send.clone();
thread::spawn(move || {
loop { // exit condition does not matter, breaking right after the 1st iteration
&thread_send.send(i).unwrap(); // have to borrow in the loop
break;
}
println!("thread {:?} finished", i);
});
}
// drop `send` needed here (as it's cloned by all producers)?
for x in recv { // hanging
println!("Got: {}", x);
}
println!("finished iterating");
}
在输出中我们可以清楚地看到线程已退出(因此线程本地克隆发件人被丢弃):
thread 0 finished
Got: 0
Got: 1
Got: 2
thread 1 finished
thread 2 finished
finished iterating
永远不会打印出来,并且进程在 playground 中中断(在本地永远挂起)。
这是什么原因?
PS。需要在线程中循环(这是实际使用的代码的简化示例)以显示真实用例。
您需要将 send
放在您的评论指示的位置,因为只有在最后一个发件人被放下时频道才会关闭。主线程的发送只有在超出函数末尾的范围时才会被丢弃。
您可以显式调用 drop(send)
或重构您的代码,以便主线程的发送在您开始我们的接收循环之前超出范围,正如 Stargateur 在评论中指出的那样 (playground)。这是可取的,因为 reader 可以立即清楚地看到 send
被删除,而 drop(send)
语句很容易被忽略。
以下代码在迭代器中挂起:(playground)
#![allow(unused)]
fn main() {
use std::sync::mpsc::channel;
use std::thread;
let (send, recv) = channel();
let num_threads = 3;
for i in 0..num_threads {
let thread_send = send.clone();
thread::spawn(move || {
loop { // exit condition does not matter, breaking right after the 1st iteration
&thread_send.send(i).unwrap(); // have to borrow in the loop
break;
}
println!("thread {:?} finished", i);
});
}
// drop `send` needed here (as it's cloned by all producers)?
for x in recv { // hanging
println!("Got: {}", x);
}
println!("finished iterating");
}
在输出中我们可以清楚地看到线程已退出(因此线程本地克隆发件人被丢弃):
thread 0 finished
Got: 0
Got: 1
Got: 2
thread 1 finished
thread 2 finished
finished iterating
永远不会打印出来,并且进程在 playground 中中断(在本地永远挂起)。
这是什么原因?
PS。需要在线程中循环(这是实际使用的代码的简化示例)以显示真实用例。
您需要将 send
放在您的评论指示的位置,因为只有在最后一个发件人被放下时频道才会关闭。主线程的发送只有在超出函数末尾的范围时才会被丢弃。
您可以显式调用 drop(send)
或重构您的代码,以便主线程的发送在您开始我们的接收循环之前超出范围,正如 Stargateur 在评论中指出的那样 (playground)。这是可取的,因为 reader 可以立即清楚地看到 send
被删除,而 drop(send)
语句很容易被忽略。