Rust中while let循环满足时间终止条件后仍未停止问题求助
问题原因与修复方案
你代码里存在两个核心问题导致循环无法正常终止:
- 首先是
while条件的逻辑错误
你使用了while let n = now.elapsed().as_secs() < 10的写法,while let的运行规则是只要右侧表达式的结果能成功匹配左侧的模式,就会执行循环体。这里你把布尔类型的判断结果赋值给变量n,不管结果是true还是false,模式匹配永远会成功,所以哪怕时间超过10秒、n的值为false,循环依然会继续执行。 - 其次是阻塞IO导致条件无法及时校验
tungstenite的read_message方法默认是阻塞调用:如果10秒超时节点到来时,没有新的WebSocket消息推送,程序会一直卡在read_message这一行等待新消息,根本不会进入下一轮循环的时间校验逻辑,自然不会主动终止。
修复方案
1. 修正循环条件
直接将时间判断作为while的普通条件即可,不需要用while let:
while now.elapsed().as_secs() < 10 { // 循环逻辑 }
2. 解决阻塞读取问题
最简单的方案是给WebSocket连接设置读取超时,让read_message最多阻塞固定时长就返回,就能及时校验时间条件,示例代码如下:
use std::time::{Instant, Duration}; use tungstenite::Error; // 设置读取超时为500毫秒,可根据需求调整 socket.set_read_timeout(Some(Duration::from_millis(500))).expect("设置读取超时失败"); let now = Instant::now(); while now.elapsed().as_secs() < 10 { let msg = match socket.read_message() { Ok(msg) => msg, // 捕获超时异常,直接进入下一轮时间校验 Err(Error::Io(e)) if e.kind() == std::io::ErrorKind::TimedOut => continue, Err(e) => panic!("读取消息错误: {}", e) }; let msg = match msg { tungstenite::Message::Text(s) => s, _ => panic!("收到非文本类型消息") }; let parsed: serde_json::Value = serde_json::from_str(&msg).expect("JSON解析失败"); let price_str = parsed["p"].as_str().unwrap(); let price: f32 = price_str.parse().unwrap(); write!(f,"1 \t").expect("写入文件失败"); write!(f, "\t\t {} \n", price).expect("写入文件失败"); }
如果你的项目运行在Tokio异步runtime下,也可以使用tokio-tungstenite的异步API配合tokio::time::timeout实现超时控制,逻辑会更简洁。
内容的提问来源于stack exchange,提问作者Per Mertesacker
相关产品推荐
相关产品推荐

