gpt4 book ai didi

Sending trait objects between threads in Rust(在Rust中的线程之间发送特征对象)

转载 作者:bug小助手 更新时间:2023-10-26 20:21:05 24 4
gpt4 key购买 nike



I'd like to send a trait object between threads, but can't figure out if it's possible. It seems like it might not be, as they apparently do not fulfill the Send trait.

我想在线程之间发送一个特征对象,但不知道这是否可能。看起来可能并非如此,因为它们显然没有实现发送特性。



The following code demonstrates what I'm trying to do:

下面的代码演示了我要做的事情:



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();
}


This fails with the following message:

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



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>]`


Trying to send a plain, unboxed trait object results in a bunch of other errors, mostly complaining about not fulfilling Send + Sized.

尝试发送一个普通的、未装箱的特征对象会导致一系列其他错误,主要是抱怨没有完成Send+Size。



I'm still fairly new to Rust, so I'm not sure if there's something I'm missing, but I get the impression that there isn't a way to convince the compiler to make the trait object Send.

我对Rust还很陌生,所以我不确定我是否遗漏了什么,但我的印象是,没有一种方法可以说服编译器让特征对象发送。



If it isn't currently possible, is there any work currently under way that may allow for this in the future?

如果目前不可能,目前有没有正在进行的工作可以在未来实现这一点?


更多回答
优秀答案推荐

It's possible. You can add a Send constraint to a trait object like this:

有可能你可以像这样给trait对象添加一个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();

更多回答

Oh, huh, that's simple enough. I guess I didn't quite understand how trait objects were actually handled. So it's not the trait that has a kind, it's the underlying object, right? So you just have to let the compiler know that the box is holding something with the trait, which also happens to fulfill Send. I think I get it now.

哦,哈,这很简单。我想我不太明白trait对象实际上是如何处理的。所以不是特质有种类,而是潜在的客体,对吧?所以你只需要让编译器知道盒子里有一些带有trait的东西,这也恰好满足Send。我想我现在明白了。

This might be useful to someone: In my case, I also required Sync trait, as in Box<dyn Bar + Send + Sync>. (My use case was for a web server using warp library).

这可能对某些人有用:在我的例子中,我还需要Sync特征,如Box。(我的用例是使用WARP库的Web服务器)。

I found the simplest thing was to require Send on all implementations of my trait like this: trait Bar : Send { .... Obviously you may not want to do that if you might have some uses that don't require Send.

我发现最简单的事情就是要求对我的特征的所有实现发送,如下所示:特征栏:发送{...显然,如果您有一些不需要发送的用途,您可能不想这样做。

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com