2

我有一个从WASM-Bindgen "canvas" 示例派生的 Rust 程序。我试图在元素的每个 JavaScriptonmousemove事件上调用一些 Rust 代码。Canvas我的代码当前成功创建了 DOM 事件(看起来)。但是,在每个触发的事件中,Firefox 开发者版开发者工具的控制台都会显示一个错误:

Uncaught Error: closure invoked recursively or destroyed already

这是我的代码的一部分:

use std::f64;
use std::sync;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;

mod canvas_manager;
use canvas_manager::CanvasManager;

#[wasm_bindgen(start)]
pub fn start() {
    let document = web_sys::window().unwrap().document().unwrap();
    let canvas = document.get_element_by_id("canvas").unwrap();
    let canvas: web_sys::HtmlCanvasElement = canvas
        .dyn_into::<web_sys::HtmlCanvasElement>()
        .map_err(|_| ())
        .unwrap();

    let manager = CanvasManager::new(canvas, 480, 480);

    manager.fill_rect_with_color(210, 12, 60, 6, "#444");
    
    manager.fill_rect_with_color(210, 462, 60, 6, "#444");
    
    manager.fill_rect_with_color(236, 236, 8, 8, "#999");

    manager.clear_canvas();

    let xPos= sync::Arc::from(sync::Mutex::new(Box::new(0f64)));

    let xPosCloned = xPos.clone();

    let a = Closure::wrap(Box::new(move || {
        let mut xPosBox = xPosCloned.lock().unwrap();
        **xPosBox += 1f64;
        //web_sys::console::log_1(&JsValue::from_f64(2.5f64));
    }) as Box<dyn FnMut()>);

    manager.canvas.set_onmousemove(Some(a.as_ref().unchecked_ref()));
}

4

1 回答 1

0

提供的代码a将在start().

您可以通过修复该问题,a.forget()但随后会引入内存泄漏。

let a = Closure::wrap(Box::new(move || {
    let mut xPosBox = xPosCloned.lock().unwrap();
    **xPosBox += 1f64;
    //web_sys::console::log_1(&JsValue::from_f64(2.5f64));
}) as Box<dyn FnMut()>);

manager.canvas.set_onmousemove(Some(a.as_ref().unchecked_ref()));
a.forget();

请看一下如何避免内存泄漏的好答案。

于 2020-08-28T23:20:41.590 回答