【问题标题】:Passing a Vec<Struct> into a new task将 Vec<Struct> 传递给新任务
【发布时间】:2023-03-20 09:25:01
【问题描述】:

我试图将自定义结构的Vector 传递给在新任务中执行的函数。我已经实现了 Clone 特征,我认为这是需要的,但显然我想要传递的向量需要实现 'static+Send 才能在闭包的环境中捕获。我不确定如何满足这些终生规范?

我正在尝试从此函数启动进程

pub fn start(server: Server, ip: &str, port: u16) {

    // Other things happening

    spawn(proc() {
        event_loop(server.events.clone(), from_conn_pool)
    });
}

fn event_loop(events: Vec<Event>, from_conn_pool: Receiver<Vec<Socket>>) {
    // Wizard magic
}

我收到的错误是:error: cannot capture variable of type rustic_io::server::Server&lt;'_&gt;, which does not fulfill 'static+Send, in a bounded closure

server.rs

pub struct Server<'a> {
    pub sockets: Vec<Socket<'a>>,
    pub events: Vec<Event<'a>>
}

event.rs

pub struct Event<'a> {
    pub name: String,
    pub execute: &'a fn(data: &str, server: super::Server)
}

impl<'a> Event<'a> {
    pub fn new(event: &str, execute: &'a fn(data: &str, server: super::Server)) -> Event<'a> {
        Event {
            name: String::from_str(event),
            execute: execute
        }
    }
}

impl<'a> Clone for Event<'a> {
    fn clone(&self) -> Event<'a> {
        Event {
            name: self.name.clone(),
            execute: self.execute
        }
    }
}

事件循环任务只会遍历各种流,如果读取的数据与某个事件名称匹配,它会触发与其关联的函数。从 Rust 文档中,我可以看到您可以通过调用 spawn 来启动一个命名函数,如下所示:

// Print something profound in a different task using a named function
fn print_message() { println!("I am running in a different task!"); }
spawn(print_message);

我相信这是我应该生成任务的方式,因为它是一个正在执行的命名函数。我假设因为我将它称为spawn(proc(){ ... }),所以它期望所有的东西都可以关闭?我尝试将任务生成为spawn(event_loop(arg, arg2)),但编译器给了我:error: mismatched types: expected proc():Send but found () (expected fn but found ())

此时,我不知道如何将 Vec&lt;Event&gt; 用于新任务?

【问题讨论】:

    标签: task rust lifetime


    【解决方案1】:

    proc() 拥有它的环境。任何进入其中的东西都必须能够被移入其中,因此必须是'staticSend

    这意味着当你写的时候

    spawn(proc() {
        event_loop(server.events.clone(), from_conn_pool)
    });
    

    它试图捕获server(因为server.events.clone()——注意它是如何为此目的捕获整个Server的;它不太可能是你想要的(你可以在proc之前做类似let events = server.events.clone();的事情然后使用events,或者你可以承认clone()调用是多余的)和from_conn_pool。你的问题是server:不一定是'static,因为你没有指定任何该类型的生命周期,因此它被推断为任意生命周期;也就是说,它可能包含一个非静态生命周期的事件,显然无法将其移至新任务。对于初学者来说,您需要Server&lt;'static&gt;

    但问题随之而来:您为什么使用&amp;'a fn(…) 而不仅仅是fn(…) 作为您的类型?如果你把整个引用的东西放在那里,你的问题就会消失。

    【讨论】:

    • 我第一次尝试这个,我有一个闭包向量而不是命名函数。为了拥有它,我需要一个生命周期说明符。一旦我了解到闭包不能被克隆,我将它们更改为fn(),并且只是假设因为闭包向量需要一个生命周期说明符,所以 fn 类型也是如此。感谢您指出这一点:)
    • 不,函数没有环境,因此不需要任何生命周期。
    猜你喜欢
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    • 2015-04-16
    • 1970-01-01
    • 2023-04-03
    相关资源
    最近更新 更多