繁体   English   中英

复制一个结构以便在另一个线程上使用

[英]Copying a struct for use on another thread

我有一个结构:

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 ,编译器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 ,但出于同样的原因,它也无法编译。

然后我决定也许可以使用channel将复制的数据推入线程中,这是基于以下理论: 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 的价值 ,并让您的来电者决定是否应该克隆,或只是一招。

作为替代解决方案,您可以使用thread::scoped并维护该线程的句柄。 这使线程可以保留引用,而无需将其复制到:

#![feature(old_io,std_misc)]

use std::thread::{self,JoinGuard};
use std::old_io::timer;
use std::time::duration::Duration;

struct MyData {
    x: i32,
}

// returns immediately
impl MyData {
    fn foo(&self) -> JoinGuard<()> { 
        thread::scoped(move || { 
            timer::sleep(Duration::milliseconds(300));
            println!("{:?}", self.x); //consider a very long operation
            timer::sleep(Duration::milliseconds(300));
        })
    }
}

fn main() {
    let d = MyData { x: 42 };
    let _thread = d.foo();
    println!("I'm so fast!");
}

暂无
暂无

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

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