[英]What is the standard way to get a Rust thread out of blocking operations?
[英]What is the correct way in Rust to create a timeout for a thread or a function?
这是我的代码:
use std::net;
use std::thread;
fn scan_port(host: &str, port: u16) -> bool {
let host = host.to_string();
let port = port;
let t = thread::spawn(move || net::TcpStream::connect((host.as_str(), port)).is_ok());
t.join().unwrap()
}
如果连接未在 N 秒内完成,如何创建线程将被终止或终止的情况?
所有这一切的原因是 Rust 无法设置套接字连接超时,所以我无法确保程序不会卡住。
正如@Shepmaster 指出的那样:终止线程是个坏主意。
相反,您可以做的是为线程提供一个Sender
,如果它已成功打开连接,它应该通过它通知您(甚至可能通过向您发送句柄)。 然后你可以让你的主线程在你希望等待的时间内sleep
。 当您的线程唤醒时,它会检查其相应的Receiver
是否有来自线程的一些生命迹象。 如果线程没有回答,只需通过删除JoinHandle
和Receiver
将其释放到野外即可。 它不像在消耗 cpu 时间(它被阻塞),也没有消耗太多内存。 如果它解除阻塞,它将检测到Sender
未连接并且可以永久关闭。
当然,你不应该有无数的这些开放线程,因为它们仍然使用资源(内存和系统线程句柄),但在正常系统上这不是什么大问题。
示例:
use std::net;
use std::thread;
use std::sync::mpsc;
fn scan_port(host: &str, port: u16) -> bool {
let host = host.to_string();
let port = port;
let (sender, receiver) = mpsc::channel();
let t = thread::spawn(move || {
match sender.send(net::TcpStream::connect((host.as_str(), port))) {
Ok(()) => {}, // everything good
Err(_) => {}, // we have been released, don't panic
}
});
thread::sleep(std::time::Duration::new(5, 0));
match receiver.try_recv() {
Ok(Ok(handle)) => true, // we have a connection
Ok(Err(_)) => false, // connecting failed
Err(mpsc::TryRecvError::Empty) => {
drop(receiver);
drop(t);
// connecting took more than 5 seconds
false
},
Err(mpsc::TryRecvError::Disconnected) => unreachable!(),
}
}
@ker 的回答将始终等待 5 秒,即使连接完成得更快。 这是一种类似的方法,超时和网络请求都发生在不同的线程上,第一个完成的获胜:
let (sender, receiver) = mpsc::channel();
let tsender = sender.clone();
let t = thread::spawn(move || {
match sender.send(Ok(net::TcpStream::connect((host.as_str(), port)))) {
Ok(()) => {}, // everything good
Err(_) => {}, // we have been released, don't panic
}
});
let timer = thread::spawn(move || {
thread::sleep(Duration::from_millis(5000));
match tsender.send(Err(MyTimeoutError)) {
Ok(()) => {}, // oops, we timed out
Err(_) => {}, // great, the request finished already
}
});
return receiver.recv().unwrap();
但只要你这样做,你不妨使用recv_timeout
代替:
let (sender, receiver) = mpsc::channel();
let t = thread::spawn(move || {
match sender.send(net::TcpStream::connect((host.as_str(), port))) {
Ok(()) => {}, // everything good
Err(_) => {}, // we have been released, don't panic
}
});
return receiver.recv_timeout(Duration::from_millis(5000));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.