在不阻塞主线程的情况下读取 IO 时出现的问题

Problems with reading IO without blocking main thread

提问人:Orcadeum 提问时间:3/26/2023 最后编辑:cafce25Orcadeum 更新时间:3/26/2023 访问量:97

问:

我有这段代码,它在内部运行,特别是在内部运行,就像这个例子一样。impl Appfn launch()

输出读取和写入必须在单独的线程中进行,以便 GUI 不会冻结。我有 treid 来使用 MIO 和 tokio 以及子流程。使用普通线程时,我在借用检查器方面遇到了问题,我太菜鸟了,无法解决。首先,这是该程序的一个片段:

let mut child = Command::new(KOTLINC_PATH)
.arg("-script")
.arg(script_path)
.stdout(Stdio::piped())
// .stderr(Stdio::piped())
.spawn()
.expect("Could not execute script");

std::thread::spawn(move || {
    let out = BufReader::new(
        child.stdout.take().expect("Could not read from stdout."),
    );

    out.lines().for_each(|line| {
        self.output.terminals[0].append(line.unwrap().as_str());
        self.output.terminals[0].append("\n");
    });
});

以下是错误:

borrowed data escapes outside of associated function
`self` escapes the associated function body here
main.rs(281, 23): `self` is a reference that is only valid in the associated function body
main.rs(281, 19): lifetime `'a` defined here
borrowed data escapes outside of associated function
argument requires that `'a` must outlive `'static`

我读过一些关于使用 Arc<Mutex 的文章<...>>但这需要更改函数签名,老实说,我也太菜鸟了,无法弄清楚这一点。将不胜感激。

更新

let mut child = Command::new(KOTLINC_PATH)
    .args(&["-script", script_path.clone().as_str()])
    .stdout(Stdio::piped())
    .spawn()
    .expect("Could not execute script");

let stdout = child.stdout.take().expect("Could not read from stdout.");

let output_clone = Arc::clone(&output);

let output_thread = thread::spawn(move || {
    let output_clone_ref = &output_clone; // Create a reference to the Arc<Mutex<String>> inside the closure

    for line in BufReader::new(stdout).lines() {
        let output_ref = output_clone_ref.lock().unwrap(); // Acquire a lock on the Mutex to modify the String

        (*output_ref).insert(line.unwrap().as_str());
        (*output_ref).insert("\n");
        drop(output_ref);
    }
});

// Gets stuck here.
output_thread.join().unwrap();
多线程 Rust FLTK

评论

0赞 Caesar 3/26/2023
解决此错误的正常方法是作用域线程,但您不能使用它,因为它会破坏解锁主循环的目的。另一种方法是制作一个并将其克隆到线程中(这应该允许“该”函数签名保持不变 - 不确定您说的是哪个函数签名),或者使用 .self.output.terminals[0]Arc<Mutex<…>>std::sync::mpsc::channel
0赞 Orcadeum 3/26/2023
好的,为了简单起见,我已将此函数移出 impl 并使输出仅为 String。我尝试实现 Arc<Mutex<...>>方式,但我收到错误“使用移动值:移动发生是因为有类型,它没有实现该特征”。我已经用我的尝试更新了这个问题。output_cloneoutput_cloneArc<Mutex<String>>Copy
0赞 Orcadeum 3/26/2023
实际上,我让它工作,但现在我的主线程被阻止等待加入调用。再次更新问题。您还可以在以下位置找到完整代码: github.com/noureldinali/kotliscript
0赞 Caesar 3/26/2023
在大多数情况下,创建一个线程然后立即加入它是没有意义的,join实际上是为了等待线程的完成。如果你只是不这样做会怎样?join
0赞 Orcadeum 3/26/2023
是的,这奏效了,谢谢。我之前确实尝试过并遇到错误,并认为这是因为我删除了连接,但这是一个不同的错误。一定只是累了。多谢!我想我应该在程序关闭时处理联接?虽然现在它并没有抱怨那么不确定,但我知道这就是它在 C 中完成的方式。

答: 暂无答案