在Rust中为线程或函数创建超时的正确方法是什么? [英] What is the correct way in Rust to create a timeout for a thread or a function?

查看:308
本文介绍了在Rust中为线程或函数创建超时的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的代码:

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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆