繁体   English   中英

同步代码的异步包装器中的 Rust 生命周期

[英]Rust lifetimes in async wrapper for sync code

我正在尝试使用具有阻塞捕获方法的相机创建Stream 阻塞调用用blocking::unblock包裹起来。

use futures::stream;
use rscam::{Camera, Config};

fn frame_stream() -> impl stream::Stream {
    let mut camera = Camera::new("/dev/video0").unwrap();

    camera.start(&Config {
        interval: (1, 30),
        resolution: (1280, 720),
        format: b"H264",
        ..Default::default()
    }).unwrap();

    stream::unfold(camera, |c| async move {
        let frame = blocking::unblock(|| c.capture().unwrap()).await;
        
        Some((frame, c))
    })
}

编译给出此错误消息:

error[E0373]: closure may outlive the current function, but it borrows `c`, which is owned by the current function
  --> src/lib.rs:15:39
   |
15 |         let frame = blocking::unblock(|| c.capture().unwrap()).await;
   |                                       ^^ - `c` is borrowed here
   |                                       |
   |                                       may outlive borrowed value `c`
   |
note: function requires argument type to outlive `'static`
  --> src/lib.rs:15:21
   |
15 |         let frame = blocking::unblock(|| c.capture().unwrap()).await;
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `c` (and any other referenced variables), use the `move` keyword
   |
15 |         let frame = blocking::unblock(move || c.capture().unwrap()).await;
   |                                       ++++

error[E0505]: cannot move out of `c` because it is borrowed
  --> src/lib.rs:17:22
   |
15 |         let frame = blocking::unblock(|| c.capture().unwrap()).await;
   |                     ------------------------------------------
   |                     |                 |  |
   |                     |                 |  borrow occurs due to use in closure
   |                     |                 borrow of `c` occurs here
   |                     argument requires that `c` is borrowed for `'static`
16 |         
17 |         Some((frame, c))
   |                      ^ move out of `c` occurs here

我如何向编译器保证闭包中对c的引用仍然有效? 我认为它会是,因为在返回c之前等待执行闭包。

解决方案

stream::unfold(camera, |c| async move {
    Some(
        blocking::unblock(|| {
            (c.capture().unwrap(), c)
        }).await
    )
})

您可以将相机移动到内部封闭中,然后在帧捕获完成后将其返回:

    stream::unfold(camera, |c| async move {
        Some(blocking::unblock(|| move {
            let frame = c.capture().unwrap()).await;
            (frame,c)
        })
    })

.await不保证活跃度。 这是作用域异步任务的普遍问题。 期货可以随时取消。 考虑:

let future = async {
    let local = 123;
    blocking::unblock(|| local).await;
};

// Poll `future`, but only once.
futures::block_on(async move { futures::poll!(future) });

我们使用本地数据开始了一项任务,然后放弃了未来。 任务继续执行,但本地数据消失了。 出于这个原因,目前没有可靠的方法来公开异步 API,从而允许使用类似于作用域线程的本地数据。 您必须使用'static数据,例如通过包装Arc

另请参阅blocking问题 #4

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM