无法捕获 fn 项目中的动态环境

OZ_*_*OZ_ 5 rust

在此代码中,除了 之外,一切正常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);
}
Run Code Online (Sandbox Code Playgroud)

错误:

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

请帮我解决这个问题 - 如何将 task_id 传递到闭包中?

She*_*ter 5

为了扩展克里斯·摩根的答案,这是一个具有相同错误的独立示例:

fn main() {
    let mut a = 0;
    fn router() {
        a += 1;
    }
    router();
    println!("{}", a)
}
Run Code Online (Sandbox Code Playgroud)

问题是fn项目不允许捕捉它们的环境,就这样。捕获环境并不简单,有多种方法可以将变量放入闭包中。闭包实际上是为每个捕获的变量提供适当成员变量的结构。

回顾克里斯·摩根的声明:

请记住它可能是多线程的;至少您需要使用某种形式的互斥体才能使其正常工作。

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

我不是镍方面的专家,但您发布的代码似乎无法实现动态路由。但是,您应该可以避免使用宏并自己构造一个处理程序,您“只”需要实现Middleware。该处理程序可能能够包含状态,就像您的task_id.