简体   繁体   English

让 Rust 线​​程脱离阻塞操作的标准方法是什么?

[英]What is the standard way to get a Rust thread out of blocking operations?

Coming from Java, I am used to idioms along the lines of来自Java,我习惯了类似的成语

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

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

Reading on how this is done in Rust, I find lots of seemingly special solutions mentioned like mio , tokio .阅读如何在 Rust 中完成此操作,我发现提到了许多看似特殊的解决方案,例如miotokio 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.我还发现ErrorKind::Interrupted并尝试通过向线程发送SIGINT来获取此ErrorKind ,但线程似乎立即死亡而没有留下任何(回溯)跟踪。

Here is the code I used (note: not very well versed in Rust yet, so it might look a bit strange, but it runs):这是我使用的代码(注意:还不是很精通 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();
}

By "blocking operations", I mean:通过“阻止操作”,我的意思是:

  • sleep睡觉
  • socket IO套接字 IO
  • file IO文件 IO
  • queue IO (not sure yet where the queues are in Rust)队列 IO(尚不确定队列在 Rust 中的位置)

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?分别向线程发出信号的方法是什么,比如 Java 中的Thread.interrupt() ,是时候打包回家了?

There is no such thing.哪有这回事。 Blocking means blocking.阻塞意味着阻塞。

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.这就是像 mio、Tokio 或 futures 这样的库的用武之地——它们处理将所有这些非阻塞、异步部分粘在一起的架构。

catch (InterruptedException e)

Rust doesn't have exceptions. Rust 没有例外。 If you expect to handle a failure case, that's better represented with a Result .如果您希望处理失败案例,最好用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:文档甚至说:

On Unix platforms this function will not return early due to a signal在 Unix 平台上,此函数不会因为信号而提前返回

Socket IO套接字 IO

You put the socket into nonblocking mode using methods like set_nonblocking and then handle ErrorKind::WouldBlock .您使用set_nonblocking等方法将套接字置于非阻塞模式,然后处理ErrorKind::WouldBlock

See also:也可以看看:

File IO文件 IO

There isn't really a good cross-platform way of performing asynchronous file IO.执行异步文件 IO 并没有真正好的跨平台方式。 Most implementations spin up a thread pool and perform blocking operations there, sending the data over something that does non-blocking.大多数实现都会启动一个线程池并在那里执行阻塞操作,通过非阻塞的方式发送数据。

See also:也可以看看:

Queue IO队列 IO

Perhaps you mean something like a MPSC channel , in which case you'd use tools like try_recv .也许您的意思是MPSC 频道之类的东西,在这种情况下,您会使用诸如try_recv类的工具。

See also:也可以看看:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM