在用Tokio做一些测试时,我注意到,当使用tokio::io::split
将写入器和读取器发送到不同的任务时,读取器部分从不等待写入器关闭,也不会等待写入部分在另一个任务中完成时进行任何写入.
我试着在文件上找到,但没有什么可以解释这一点的原因.
我是不是错过了什么?
这是一个重现它的最小代码.
use std::io::Cursor;
use tokio::io::{self, AsyncReadExt, AsyncWriteExt};
use tokio::spawn;
#[tokio::main]
async fn main() {
let a = Cursor::new(vec![]);
let (mut read, mut write) = io::split(a);
spawn(async move {
for i in 0..10 {
write.write_all(&[i]).await.unwrap();
}
});
let mut output = vec![];
let written = read.read_buf(&mut output).await.unwrap();
assert_eq!(written, 10);
}
它可以从here开始执行.
操场上的输出如下:
Execution
Format
Share
Close
Standard Error
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 1.60s
Running `target/debug/playground`
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `0`,
right: `10`', src/main.rs:20:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Standard Output
它只返回0而不是10.
我认为这是因为Cursor<Vec<_>>
的唤醒程序总是处于准备状态是有意义的,因为没有执行IO(假设),除非您正在将数据从其他地方通过管道传输到游标中.
我也try 了yield_now
或sleep
,但它从未得到任何写入的数据.
我还确保写入器被移动,以便它可以在丢弃时刷新和剩余数据,并关闭它可能拥有的任何句柄.
在正常的游标中,我必须将其定位到位置0,但是,这不会违背拆分的目的吗?