使Rust线程退出阻塞操作的标准方法是什么? [英] What is the standard way to get a Rust thread out of blocking operations?
问题描述
来自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中的完成方式,我发现了许多看似特殊的解决方案,例如mio
,tokio
.我还找到了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:
- 睡觉
- socket 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或futures之类的库进入的地方-它们处理将所有这些非阻塞的异步块粘贴在一起的体系结构.
Instead, you deliberately use tools that are non-blocking. That's where libraries like mio or futures come in — they handle the architecture of sticking all of this 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平台上,此功能不会由于信号而提前返回
套接字IO
您可以使用 set_nonblocking
,然后处理 ErrorKind::WouldBlock
.
Socket IO
You put the socket into nonblocking mode using methods like set_nonblocking
and then handle 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
.
另请参阅:
- How to terminate or suspend a Rust thread from another thread?
- What is the best approach to encapsulate blocking I/O in future-rs?
- What does java.lang.Thread.interrupt() do?
这篇关于使Rust线程退出阻塞操作的标准方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!