2016-07-11 5 views
0

チャンネル経由でカスタム構造体を送信するのに苦労しています。チャネルを介して構造体を送信できません:mpsc :: Senderはスレッド間で安全に共有できません

ArcMutexの値をチュートリアル に記載されているようにラップしましたが、とにかくコンパイルされません。

extern crate num; 

use num::bigint::BigInt; 
use std::io::{self, Write}; 
use std::sync::mpsc; 
use std::thread; 
use readline::readline as ask; 
use std::sync::{Arc, Mutex}; 

enum Command { 
    Quit, 
    Help, 
    Factorial { n: BigInt }, 
    Error { msg: String }, 
} 

fn main() { 
    let (input_tx, input_rx) = mpsc::channel(); 
    let input_thread = thread::spawn(|| { 
     input_tx.send(Arc::new(Mutex::new(Command::Quit))); 
    }); 
} 
error: the trait bound `std::sync::mpsc::Sender<std::sync::Arc<std::sync::Mutex<Command>>>: std::marker::Sync` is not satisfied [E0277] 
    let input_thread = thread::spawn(|| { 
         ^~~~~~~~~~~~~ 
help: run `rustc --explain E0277` to see a detailed explanation 
note: `std::sync::mpsc::Sender<std::sync::Arc<std::sync::Mutex<Command>>>` cannot be shared between threads safely 
note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Sender<std::sync::Arc<std::sync::Mutex<Command>>>` 
note: required because it appears within the type `[[email protected]/main.rs:25:38: 65:6 input_tx:&std::sync::mpsc::Sender<std::sync::Arc<std::sync::Mutex<Command>>>]` 
note: required by `std::thread::spawn` 
error: aborting due to previous error 

私は錆1.10.0(cfcb716cf 2016年7月3日)を使用しています。

+1

注:チャネル内で値をラップしましたが、コンパイラはここでラッピングされていないチャネルの*送信側*について不平を言っています。 –

答えて

2

thread::spawn()に渡されるクロージャは、moveFnOnce)である必要があります。 ArcMutexが必要とされていません。

let input_thread = thread::spawn(move || { 
    input_tx.send(Command::Quit); 
}); 
1

ルックMCVEこの時:

use std::thread; 
use std::sync::mpsc; 

enum Command { 
    Quit, 
    Error { msg: String }, 
} 

fn main() { 
    let (input_tx, input_rx) = mpsc::channel(); 
    let input_thread = thread::spawn(|| { 
     input_tx.send(Command::Quit); 
    }); 
} 

、エラーメッセージ:

`のstd ::同期:: MPSC :: Sender`することはできませんスレッド間で安全に共有できます。 :: Sender`ため&のstd ::同期:: MPSC `のためのstd ::マーカー:: Send``のIMPL上の要件のために必要な

(強調鉱山)デフォルトでは

クロージャは、の中に使用されている任意の変数への参照をキャプチャします。所有権を放棄することは、クロージャの作成者にとってより制限的であるため、ほとんどの場合、これが必要です。参照を使用すると、キャプチャされた値をクロージャーの内側と内側の間で共有することができ、ビットを動かす必要はありません。

この場合、するは、閉鎖にinput_txの所有権を与えたいと思います。これは、クロージャ自身の所有権が新しいスレッドに与えられるため、クロージャとその中のすべてが別のスレッドに渡されることが安全である必要があるためです。 参照Senderは、スレッド間で共有されていない可能性があります。

move closureは、キャプチャされた変数の所有権がクロージャに転送されるように要求します。これを行うことで、共有がなくなり、すべての要件が満たされます。 aSpex said通り:

時折
let input_thread = thread::spawn(move || { 
    input_tx.send(Command::Quit); 
}); 

あなたには、いくつかの捕獲変数の所有権を譲渡する必要がなく、他人を共有したいです。 moveのクロージャはすべてまたはすべてであるため、この場合はより明示的にする必要があります。あなたは、単に閉鎖する前に参照を取ることができます。aへの参照が'staticではなく、一般的な考え方を示しているため

let a = 42; 
let a_ref = &a; 

let input_thread = thread::spawn(move || { 
    println!("{}", a_ref); 
}); 

これは動作しません。

関連する問題