Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何从另一个螺纹终止或挂起生锈的螺纹?_Multithreading_Rust - Fatal编程技术网

Multithreading 如何从另一个螺纹终止或挂起生锈的螺纹?

Multithreading 如何从另一个螺纹终止或挂起生锈的螺纹?,multithreading,rust,Multithreading,Rust,编者按-此示例是在Rust 1.0之前创建的,此后特定类型已更改或删除。一般问题和概念仍然有效 我已经产生了一个线程,里面有一个无限循环和计时器 thread::spawn(|| { let mut timer = Timer::new().unwrap(); let periodic = timer.periodic(Duration::milliseconds(200)); loop { periodic.recv(); // Do

编者按-此示例是在Rust 1.0之前创建的,此后特定类型已更改或删除。一般问题和概念仍然有效

我已经产生了一个线程,里面有一个无限循环和计时器

thread::spawn(|| {
    let mut timer = Timer::new().unwrap();
    let periodic = timer.periodic(Duration::milliseconds(200));
    loop {
        periodic.recv();

        // Do my work here
    }
});
基于某些条件,经过一段时间后,我需要从程序的另一部分终止此线程。换句话说,我想退出无限循环。如何才能正确地执行此操作?此外,我如何暂停此线程并在以后继续


我尝试使用全局不安全标志来中断循环,但我认为这个解决方案看起来不太好。

对于终止和挂起线程,您可以使用通道

外部终止 在worker循环的每次迭代中,我们检查是否有人通过通道通知我们。如果是,或者通道的另一端超出范围,我们将中断循环

use std::io::{self, BufRead};
use std::sync::mpsc::{self, TryRecvError};
use std::thread;
use std::time::Duration;

fn main() {
    println!("Press enter to terminate the child thread");
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || loop {
        println!("Working...");
        thread::sleep(Duration::from_millis(500));
        match rx.try_recv() {
            Ok(_) | Err(TryRecvError::Disconnected) => {
                println!("Terminating.");
                break;
            }
            Err(TryRecvError::Empty) => {}
        }
    });

    let mut line = String::new();
    let stdin = io::stdin();
    let _ = stdin.lock().read_line(&mut line);

    let _ = tx.send(());
}
use std::io::{self, BufRead};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn main() {
    println!("Press enter to wake up the child thread");
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || loop {
        println!("Suspending...");
        match rx.recv() {
            Ok(_) => {
                println!("Working...");
                thread::sleep(Duration::from_millis(500));
            }
            Err(_) => {
                println!("Terminating.");
                break;
            }
        }
    });

    let mut line = String::new();
    let stdin = io::stdin();
    for _ in 0..4 {
        let _ = stdin.lock().read_line(&mut line);
        let _ = tx.send(());
    }
}
暂停和恢复 我们使用
recv()
,它挂起线程,直到有东西到达通道。为了恢复线程,您需要通过通道发送一些内容;在这种情况下,单位值为
()
。如果信道的传输端被丢弃,
recv()
将返回
Err(())
-我们使用它退出循环

use std::io::{self, BufRead};
use std::sync::mpsc::{self, TryRecvError};
use std::thread;
use std::time::Duration;

fn main() {
    println!("Press enter to terminate the child thread");
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || loop {
        println!("Working...");
        thread::sleep(Duration::from_millis(500));
        match rx.try_recv() {
            Ok(_) | Err(TryRecvError::Disconnected) => {
                println!("Terminating.");
                break;
            }
            Err(TryRecvError::Empty) => {}
        }
    });

    let mut line = String::new();
    let stdin = io::stdin();
    let _ = stdin.lock().read_line(&mut line);

    let _ = tx.send(());
}
use std::io::{self, BufRead};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn main() {
    println!("Press enter to wake up the child thread");
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || loop {
        println!("Suspending...");
        match rx.recv() {
            Ok(_) => {
                println!("Working...");
                thread::sleep(Duration::from_millis(500));
            }
            Err(_) => {
                println!("Terminating.");
                break;
            }
        }
    });

    let mut line = String::new();
    let stdin = io::stdin();
    for _ in 0..4 {
        let _ = stdin.lock().read_line(&mut line);
        let _ = tx.send(());
    }
}
其他工具
渠道是完成这些任务最简单、最自然(IMO)的方式,但不是最有效的方式。您可以在模块中找到其他并发原语。它们属于比通道更低的级别,但在特定任务中效率更高

理想的解决方案是a。您可以在
std::sync模块中使用,如下所示

这是文档中的示例:


我自己已经多次回过这个问题,下面是我认为能够解决OP的意图和其他人让线程停止自身的最佳实践的内容。基于公认的答案,这是对mpsc的一个很好的升级,允许克隆和移动消息端点。它还具有方便的勾号功能。这里真正的要点是它有try_recv(),它是非阻塞的

我不确定把消息检查器放在这样一个操作循环的中间是多么有用。我还没有发现Actix(或以前的Akka)能够在没有(如上所述)让线程自己完成任务的情况下真正停止线程。所以这就是我现在正在使用的(这里有很大的修正余地,我还在学习自己)

//Cargo.toml:
//[依赖关系]
//横梁通道=“0.4.4”
使用横梁_通道:{发送方,接收方,无界,勾选};
使用std::time::{Duration,Instant};
fn main(){
let(tx,rx):(发送方,接收方)=无界();
设rx2=rx.clone();
//横梁允许克隆和移动接收器
std::thread::spawn(移动| |){
//作品:
//让mut timer=timer::new().unwrap();
//设periodic=timer.periodic(持续时间:毫秒(200));
让ticker:Receiver=tick(std::time::Duration::from_millis(500));
环路{
//作品:
//periodic.recv();
横梁_通道::选择{
recv(股票代码)->{
//OP:在这里做我的工作
println!(“你好,工作。”);
//通信检查:继续工作?
//try_recv是非阻塞的
//rx,单个耗电元件可在横梁中克隆
让try_result=rx2。try_recv();
匹配try_结果{
Err(_e)=>{},
Ok(msg)=>{
匹配msg.as_str(){
“结束世界”=>{
println!(“世界末日”);
打破
},
_ => {},
}
},
_ => {}
}
}
}
}
});
//让工作继续10秒钟,然后告诉线程结束。
std::thread::sleep(std::time::Duration::from_secs(10));
println!(“再见,世界”);
发送(“结束世界”。发送到字符串());
}

对我来说,使用字符串作为消息设备有点畏缩。可以在枚举中执行其他挂起和重新启动操作。

为了与其他人共享,@RajeevRanjan建议的解决方案解决了我正在维护的火箭项目中的一个大问题。Rocket框架不包含关闭功能,因此我启动了一个新线程来处理服务器,并使用
Condvar
等待它。我尝试使用
mpsc
,但使用
Condvar
更简单。代码可用。@silvioprog我没有提供此建议;我只是编辑了它。RajeevRanjan是解决方案的作者。当你的线程正在运行阻塞操作时,你看不出该如何工作。@hasufell它不会,但是答案无论如何也不会这样说。如果没有线程方面的合作,就不可能以安全、便携的方式停止线程。渠道是这种合作的一种方式。