【问题标题】:Can't capture dynamic environment in a fn item无法在 fn 项目中捕获动态环境
【发布时间】:2015-04-14 00:46:26
【问题描述】:

在这段代码中,除了task_id 之外,一切正常。我希望这个脚本计算task_id中的请求:

use std::thread;
use std::thread::sleep_ms;
use std::sync::mpsc;
#[macro_use] extern crate nickel;
use nickel::Nickel;

fn main() {
    let mut server = Nickel::new();
    let mut task_id: i64 = 0;

    server.utilize(router! {
        get "**" => |_req, _res| {
            task_id += 1;
            run_heavy_task(task_id);
            "Yo!"
        }
    });

    server.listen("127.0.0.1:6767");
}

fn run_heavy_task(task_id: i64) {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        println!("heavy task {} started!", task_id);
        sleep_ms(3000);
        println!("heavy task {} completed", task_id);
        let result = tx.send(());
    });


    //rx.recv();
    //println!("Task {} completed", task_id);
}

错误:

无法在 fn 项目中捕捉动态环境;使用 || { ... } 闭包形式改为 main.rs:13 task_id += 1;

请帮我解决这个问题 - 我怎样才能将 task_id 传递给闭包?

【问题讨论】:

  • router! 是扩展为函数的糖 (github.com/nickel-org/nickel.rs/blob/master/src/macros.rs)。函数不能关闭变量,这种方法也不起作用。请记住它可能是多线程的;至少你需要使用某种形式的互斥锁来让它工作。
  • @ChrisMorgan 正如我所说,没有 task_id 的这段代码可以正常工作:gist.github.com/jamm/d067307206c8420c7388,“这种方法也不会工作”是错误的陈述。 “至少你需要使用某种形式的互斥锁才能让它工作” - 我不会在衍生函数中更改 task_id,所以我不需要互斥锁。
  • @OZ_:你误会了我想,Chris的意思是router!创建的函数改变了task_id,并且这个函数可能被多个线程调用(就Rust编译器而言)知道),所以即使它可以关闭变量(它不能),你也需要某种形式的同步。

标签: rust


【解决方案1】:

为了扩展 Chris Morgan 的答案,这是一个具有相同错误的独立示例:

fn main() {
    let mut a = 0;
    fn router() {
        a += 1;
    }
    router();
    println!("{}", a)
}

问题在于fn 项目不允许捕获它们的环境,句号。捕获环境并非易事,有多种方法可以将变量放入闭包中。闭包实际上是结构,每个捕获的变量都有相应的成员变量。

查看 Chris Morgan 的声明:

记住它可能是多线程的;至少你需要使用某种形式的互斥锁来让它工作。

(强调我的)。您正在创建一个函数,但您无法控制调用它的方式或时间。如您所知,Nickel 可能会选择从多个线程中调用它——这取决于库。事实上,永远不会调用代码task_id += 1

我不是镍方面的专家,但您发布的代码似乎无法实现动态路由。但是,您应该可以避免使用宏和construct a handler yourself,您“只”需要实现Middleware。该处理程序可能能够包含状态,例如您的 task_id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-11
    • 2014-06-16
    • 2020-08-10
    • 1970-01-01
    • 2020-01-16
    • 2018-05-29
    • 2023-02-05
    • 1970-01-01
    相关资源
    最近更新 更多