簡體   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