use std::iter;
fn worker_sum(from: u64, to: u64) -> u64 {
range(from, to).fold(0u64, |sum, x| sum + x)
}
fn main() {
let max = 5u64;
let step = 2u64;
let (sender, receiver) = channel::<u64>();
for x in iter::range_step_inclusive(0u64, max, step) {
let end = if x + step > max { max } else { x + step };
//println!("{} -> {} = {}", x, end, worker_sum(x, end));
let local_sender = sender.clone();
spawn(proc(){
local_sender.send(worker_sum(x, end));
});
}
loop {
match receiver.try_recv() {
Ok(x) => println!("{}", x),
Err(_) => break,
}
}
}
我收到错误:
任务''在关闭频道发送'失败',/ home / runbuild / src / hub-buildbot / slav / nightly-linux / build / src / libsync / comm / mod.rs:573
我以某种方式了解问题,但如何正确地从频道“选择”?虽然我正在使用每晚构建,但据说这些文档已经改进了文档(从版本0.13开始),因此文档非常稀疏。
所以我的问题是:
答案 0 :(得分:3)
您遇到的问题是,在发送所有数据之前,通道会被读取任务关闭。你的循环是:
loop {
match receiver.try_recv() {
Ok(x) => println!("{}", x),
Err(_) => break,
}
}
在此循环中,您的接收器会在遇到错误时立即中断。一旦循环中断,您的函数将到达其范围的末尾,接收器将被销毁。完成此操作后,任何发送更多数据的尝试都将失败。
问题在于,您的收件人会收到Err(Empty)
,因为发件人尚未发送任何内容。您必须等待它们,并且只有在遇到Err(Disconnected)
您需要将代码更改为此类代码(注释中的说明):
use std::iter;
fn worker_sum(from: u64, to: u64) -> u64 {
range(from, to).fold(0u64, |sum, x| sum + x)
}
fn main() {
let max = 5u64;
let step = 2u64;
let (sender, receiver) = channel::<u64>();
for x in iter::range_step_inclusive(0u64, max, step) {
let end = if x + step > max { max } else { x + step };
// here, each thread will own its own sender, and the channel will
// be closed once all senders are destroyed.
let local_sender = sender.clone();
spawn(proc(){
local_sender.send(worker_sum(x, end));
// Once we reach here, the sender of this task is destroyed.
});
}
// We destroy the sender of the main task,
// because we don't want to wait for it:
// it would deadlock the program
drop(sender);
loop {
match receiver.try_recv() {
Ok(x) => println!("{}", x),
// We break only if the channel is closed,
// it means that all senders are finished.
Err(e) if e == ::std::comm::Disconnected => { break; },
_ => {}
}
}
}