【问题标题】:What is the standard way to get a Rust thread out of blocking operations?让 Rust 线​​程脱离阻塞操作的标准方法是什么?
【发布时间】:2019-02-27 03:32:36
【问题描述】:

来自Java,我习惯了类似的成语

while (true) {
  try {
    someBlockingOperation();
  } catch (InterruptedException e) {
    Thread.currentThread.interrupt(); // re-set the interrupted flag
    cleanup(); // whatever is necessary
    break;
  }
}

据我所知,这适用于整个 JDK 中的任何可能阻塞的内容,例如从文件、套接字、队列甚至 Thread.sleep() 读取。

阅读如何在 Rust 中完成此操作,我发现提到了许多看似特殊的解决方案,例如 miotokio。我还找到了ErrorKind::Interrupted,并尝试通过将SIGINT 发送到线程来获取此ErrorKind,但线程似乎立即死亡而没有留下任何(返回)痕迹。

这是我使用的代码(注意:还不是很精通 Rust,所以它可能看起来有点奇怪,但它可以运行):

use std::io;
use std::io::Read;
use std::thread;

pub fn main() {
    let sub_thread = thread::spawn(|| {
        let mut buffer = [0; 10];
        loop {
            let d = io::stdin().read(&mut buffer);
            println!("{:?}", d);
            let n = d.unwrap();
            if n == 0 {
                break;
            }
            println!("-> {:?}", &buffer[0..n]);
        }
    });

    sub_thread.join().unwrap();
}

“阻塞操作”是指:

  • 睡觉
  • socket IO
  • 文件 IO
  • 队列 IO(尚不确定队列在 Rust 中的位置)

分别以什么方式向线程(如 Java 中的 Thread.interrupt())发出信号,表明该收拾行李回家了?

【问题讨论】:

    标签: multithreading rust terminate


    【解决方案1】:

    没有这样的事情。阻塞意味着阻塞。

    相反,您故意使用非阻塞的工具。这就是诸如 mio、Tokio 或 futures 之类的库的用武之地——它们处理将所有这些非阻塞、异步部分粘在一起的架构。

    catch (InterruptedException e)

    Rust 没有例外。如果您希望处理失败案例,最好用Result 表示。

    Thread.interrupt()

    这实际上并没有做任何事情,除了在线程中设置一个标志,一些代码可能会检查然后抛出一个异常。您可以自己构建相同的结构。一个简单的实现:

    use std::{
        sync::{
            atomic::{AtomicBool, Ordering},
            Arc,
        },
        thread,
        time::Duration,
    };
    
    fn main() {
        let please_stop = Arc::new(AtomicBool::new(false));
    
        let t = thread::spawn({
            let should_i_stop = please_stop.clone();
            move || {
                while !should_i_stop.load(Ordering::SeqCst) {
                    thread::sleep(Duration::from_millis(100));
                    println!("Sleeping");
                }
            }
        });
    
        thread::sleep(Duration::from_secs(1));
        please_stop.store(true, Ordering::SeqCst);
        t.join().unwrap();
    }
    

    睡觉

    据我所知,没有办法打断。文档甚至说:

    在 Unix 平台上,此函数将由于信号而不会提前返回

    Socket IO

    您使用set_nonblocking 等方法将套接字置于非阻塞模式,然后处理ErrorKind::WouldBlock

    另见:

    文件 IO

    实际上并没有一种很好的跨平台方式来执行异步文件 IO。大多数实现都会启动一个线程池并在那里执行阻塞操作,通过非阻塞的方式发送数据。

    另见:

    队列 IO

    也许您的意思是MPSC channel,在这种情况下您会使用try_recv 之类的工具。

    另见:

    【讨论】:

      猜你喜欢
      • 2019-09-24
      • 1970-01-01
      • 1970-01-01
      • 2010-10-11
      • 2012-06-13
      • 1970-01-01
      • 2020-05-10
      • 2011-04-15
      • 2014-06-15
      相关资源
      最近更新 更多