让 Rust 线​​程摆脱阻塞操作的标准方法是什么? [英] What is the standard way to get a Rust thread out of blocking operations?

查看:12
本文介绍了让 Rust 线​​程摆脱阻塞操作的标准方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自Java,我习惯了

Coming from Java, I am used to idioms along the lines of

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

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

This works, as far as I know, across the whole JDK for anything that might block, like reading from files, from sockets, from a queue and even for Thread.sleep().

阅读有关如何在 Rust 中完成此操作的文章,我发现提到了许多看似特殊的解决方案,例如 miotokio.我还找到了 ErrorKind::Interrupted 并试图通过将 SIGINT 发送到线程来获取此 ErrorKind,但该线程似乎没有离开就立即死亡任何(回)迹.

Reading on how this is done in Rust, I find lots of seemingly special solutions mentioned like mio, tokio. I also find ErrorKind::Interrupted and tried to get this ErrorKind with sending SIGINT to the thread, but the thread seems to die immediately without leaving any (back)trace.

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

Here is the code I used (note: not very well versed in Rust yet, so it might look a bit strange, but it runs):

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();
}

通过阻塞操作",我的意思是:

By "blocking operations", I mean:

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

向线程发出信号的各自方法是什么,例如 Java 中的 Thread.interrupt(),是时候收拾行装回家了?

What would be the respective means to signal to a thread, like Thread.interrupt() in Java, that its time to pack up and go home?

推荐答案

没有这样的事情.阻塞就是阻塞.

There is no such thing. Blocking means blocking.

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

Instead, you deliberately use tools that are non-blocking. That's where libraries like mio, Tokio, or futures come in — they handle the architecture of sticking all of these non-blocking, asynchronous pieces together.

catch (InterruptedException e)

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

Rust doesn't have exceptions. If you expect to handle a failure case, that's better represented with a Result.

Thread.interrupt()

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

This doesn't actually do anything beyond setting a flag in the thread that some code may check and then throw an exception for. You could build the same structure yourself. One simple implementation:

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();
}

睡觉

据我所知,无法打断.文档甚至说:

Sleep

No way of interrupting, as far as I know. The documentation even says:

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

On Unix platforms this function will not return early due to a signal

套接字 IO

您使用诸如 set_nonblocking 然后处理 ErrorKind::WouldBlock.

另见:

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

There isn't really a good cross-platform way of performing asynchronous file IO. Most implementations spin up a thread pool and perform blocking operations there, sending the data over something that does non-blocking.

另见:

也许您指的是 MPSC 频道,在这种情况下,您将使用诸如 <代码>try_recv.

Perhaps you mean something like a MPSC channel, in which case you'd use tools like try_recv.

另见:

这篇关于让 Rust 线​​程摆脱阻塞操作的标准方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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