![](/img/trans.png)
[英]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.