【问题标题】:Sending trait objects between threads in Rust在 Rust 中的线程之间发送 trait 对象
【发布时间】:2014-09-03 16:32:49
【问题描述】:

我想在线程之间发送一个特征对象,但不知道是否可行。看起来可能不是,因为它们显然不符合 Send 特征。

以下代码演示了我正在尝试做的事情:

use std::{
    sync::mpsc::{channel, Receiver, Sender},
    thread,
};

trait Bar {
    fn bar(&self);
}

struct Foo {
    foo: i32,
}

impl Bar for Foo {
    fn bar(&self) {
        println!("foo: {}", self.foo);
    }
}

fn main() {
    let foo = Box::new(Foo { foo: 1 }) as Box<dyn Bar>;

    let (tx, rx): (Sender<Box<dyn Bar>>, Receiver<Box<dyn Bar>>) = channel();

    thread::spawn(move || {
        tx.send(foo).unwrap();
    });

    let sent = rx.recv().unwrap();

    sent.bar();
}

此操作失败并显示以下消息:

error[E0277]: `dyn Bar` cannot be sent between threads safely
   --> src/main.rs:25:5
    |
25  |     thread::spawn(move || {
    |     ^^^^^^^^^^^^^ `dyn Bar` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `dyn Bar`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dyn Bar>`
    = note: required because it appears within the type `std::boxed::Box<dyn Bar>`
    = note: required because it appears within the type `[closure@src/main.rs:25:19: 27:6 tx:std::sync::mpsc::Sender<std::boxed::Box<dyn Bar>>, foo:std::boxed::Box<dyn Bar>]`

尝试发送一个普通的、未装箱的 trait 对象会导致一系列其他错误,主要是抱怨不满足 Send + Sized

我对 Rust 还是很陌生,所以我不确定我是否缺少某些东西,但我的印象是没有办法说服编译器生成 trait 对象Send .

如果目前不可行,是否有任何正在进行的工作可能会在未来允许这样做?

【问题讨论】:

    标签: rust trait-objects


    【解决方案1】:

    这是可能的。您可以将Send 约束添加到特征对象,如下所示:

    let foo = Box::new(Foo { foo: 1 }) as Box<dyn Bar + Send>;
    
    let (tx, rx): (Sender<Box<dyn Bar + Send>>, Receiver<Box<dyn Bar + Send>>) = channel();
    

    【讨论】:

    • 哦,嗯,这很简单。我想我不太明白 trait 对象的实际处理方式。因此,拥有种类的不是特质,而是潜在的对象,对吧?所以你只需要让编译器知道盒子里有一些具有特征的东西,这也恰好满足Send。我想我现在明白了。
    • 这可能对某人有用:就我而言,我还需要Sync trait,如Box&lt;dyn Bar + Send + Sync&gt;。 (我的用例是使用 warp 库的 Web 服务器)。
    • 我发现最简单的方法是在我的 trait 的所有实现上要求 Send,如下所示:trait Bar : Send { ...。显然,如果您可能有一些不需要 Send 的用途,您可能不想这样做。
    猜你喜欢
    • 1970-01-01
    • 2017-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    相关资源
    最近更新 更多