使Rust线程退出阻塞操作的标准方法是什么?

Har*_*ald 4 multithreading terminate rust

来自Java,我习惯于遵循以下习惯用法

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

据我所知,它可以在整个JDK中处理任何可能阻塞的内容,例如从文件读取,从套接字读取,从队列读取甚至对于Thread.sleep()

阅读有关如何在Rust中完成此操作的信息,我发现了许多看似特殊的解决方案,例如miotokio。我也找到ErrorKind::Interrupted并尝试ErrorKind通过发送SIGINT到线程来解决这个问题,但是线程似乎立即死亡而没有留下任何(返回)跟踪。

这是我使用的代码(注意: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();
}
Run Code Online (Sandbox Code Playgroud)

我所说的“阻止操作”是指:

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

Thread.interrupt()Java中一样,用信号通知线程该打包并回家​​了吗?

She*_*ter 5

哪有这回事。阻塞意味着阻塞。

相反,您故意使用非阻塞工具。那就是像mio或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();
}
Run Code Online (Sandbox Code Playgroud)

睡觉

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

在Unix平台上,此功能不会由于信号而提前返回

插槽IO

您可以使用类似方法将套接字置于非阻塞模式set_nonblocking,然后使用handle ErrorKind::WouldBlock

文件IO

实际上,没有很好的跨平台方法来执行异步文件IO。大多数实现会启动线程池并在其中执行阻塞操作,通过不阻塞的东西发送数据。

队列IO

也许您的意思是类似MPSC频道,在这种情况下,您将使用try_recv

也可以看看: