我有一个结构:
struct MyData {
x: i32
}
我想在此结构上异步启动长操作。
我的第一次尝试是:
fn foo(&self) { //should return immediately
std::thread::Thread::spawn(move || {
println!("{:?}",self.x); //consider a very long operation
});
}
显然,cannot infer an appropriate lifetime due to conflicting requirements
由于编译器self
可能位于堆栈框架上,因此不能保证在操作在其他堆栈框架上运行时就存在该编译器。
为了解决这个问题,我尝试制作一个副本self
并将其提供给新线程:
fn foo(&self) { //should return immediately
let clone = self.clone();
std::thread::Thread::spawn(move || {
println!("{:?}",clone.x); //consider a very long operation
});
}
我认为这不能编译,因为现在clone
在堆栈框架上,与以前类似。我也尝试clone
在线程内部进行操作,出于同样的原因,我也认为它也不能编译。
然后我决定也许可以使用achannel
将复制的数据推入线程中,这一理论可能channel
可以在线程之间神奇地移动(复制?)堆栈分配的数据,该示例在文档中提出。但是,编译器无法为此推断寿命:
fn foo(&self) { //should return immediately
let (tx, rx) = std::sync::mpsc::channel();
tx.send(self.clone());
std::thread::Thread::spawn(move || {
println!("{:?}",rx.recv().unwrap().x); //consider a very long operation
});
}
最后,我决定只是将我的结构显式复制到堆上,然后将Arc传递到线程中。但即使在这里,编译器也无法确定生命周期:
fn foo(&self) { //should return immediately
let arc = std::sync::Arc::new(self.clone());
std::thread::Thread::spawn(move || {
println!("{:?}",arc.clone().x); //consider a very long operation
});
}
好吧,借支票员,我放弃。如何将的副本复制self
到新线程上?
我认为您的问题仅仅是因为您的结构没有派生出Clone
特质。您可以通过#[derive(Clone)]
在结构定义之前添加来获取第二个示例进行编译和运行。
我在此处的编译器行为中不了解的是.clone()
它尝试在此处使用的功能。您的结构确实没有实现Clone
特征,因此默认情况下不应具有.clone()
功能。
您可能还需要考虑在函数中self
按value取值,并让调用者决定是应进行克隆还是仅进行移动。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句