在Rust中为线程或函数创建超时的正确方法是什么? [英] What is the correct way in Rust to create a timeout for a thread or a function?
问题描述
这是我的代码:
use std::net;
use std::thread;
extern crate argparse;
use argparse::{ArgumentParser, StoreTrue, Store};
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秒内未完成,如何创建线程将终止或终止的情况?
How do I create a situation where the thread will be terminated or killed if the connection didn't finish in N seconds?
所有这些的原因是Rust无法设置套接字连接超时,因此我无法确保程序不会卡住.
The reason for all of this is that Rust has no way to set a socket connection timeout so I have no way to ensure the program won't get stuck.
推荐答案
正如@Shepmaster所说:终止线程是一个坏主意.
As @Shepmaster noted: it's a bad idea to terminate threads.
相反,您可以给线程添加 Sender
通过它应该通知您是否已成功打开连接(甚至可以通过发送句柄).然后,可以让主线程 sleep
等待.当您的线程唤醒时,它将检查其相应的 Receiver
从线程的生命.万一线程没有回答,只需通过放下JoinHandle
将其释放a>和Receiver
.这不像是在消耗CPU时间(它被阻止),也不是在消耗太多内存.如果解除阻止,它将检测到Sender
未连接,并且可以永久关闭.
What you can do instead is to give the thread a Sender
through which it should notify you if it has successfully opened a connection (maybe even by sending you the handle). Then you can let your main thread sleep
for the time you wish to wait. When your thread wakes up, it checks its corresponding Receiver
for some sign of life from the thread. In case the thread did not answer, just release it into the wild by dropping the JoinHandle
and the Receiver
. It's not like it's consuming cpu-time (it's blocked), and it's not consuming too much memory. If it ever unblocks, it'll detect that the Sender
is not connected and can shut down for good.
当然,您不应该拥有成千上万个这样的开放线程,因为它们仍在使用资源(内存和系统线程句柄),但是在普通系统上,这没什么大问题.
Of course you should not have bazillions of these open threads, because they still use resources (memory and system thread handles), but on a normal system that's not too much of an issue.
示例:
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!(),
}
}
这篇关于在Rust中为线程或函数创建超时的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!