2017-01-08 50 views
1

我想在線程中使用閉包,但在嘗試2小時後我似乎無法找到如何。這裏的文件discord_async.rs在線程中使用閉包

use discord::*; 
use discord::model::Event; 
use std::sync::Arc; 
use shared_mutex::SharedMutex; 
use std::thread; 

pub struct DiscordAsync { 
    client: Arc<SharedMutex<Discord>> 
} 

impl DiscordAsync { 
    pub fn new(bot_token: &str) -> DiscordAsync { 
     let client = Arc::new(SharedMutex::new(Discord::from_bot_token(bot_token).unwrap())); 
     DiscordAsync { 
      client: client 
     } 
    } 

    pub fn start<F>(&self, mut event_handle: F) ->() where F: FnMut(Arc<Event>, Arc<SharedMutex<Discord>>) + Send + 'static { 
     let (mut connection, _) = self.client.read().unwrap().connect().unwrap(); 
     let event_handle = Arc::new(SharedMutex::new(event_handle)); 

     loop { 
      let event = Arc::new(connection.recv_event().unwrap()); 
      let event_handle = event_handle.read().unwrap(); 

      // Start a thread so we don't block shit 
      thread::spawn(move || { 

       // Match event to actions we want to handle 
       event_handle(event.clone(), self.client); 
      }); 
     } 
    } 
} 

main.rs這樣使用它:

extern crate colored; 
extern crate discord; 
extern crate shared_mutex; 

mod discord_async; 

use std::thread; 
use colored::*; 
use discord::*; 
use discord::model::{Event, Channel, ServerId}; 
use discord_async::DiscordAsync; 

fn main() { 
    // Server info 
    let bot_token = "..."; 
    let server_id = ServerId(12345); 

    let dis_async = DiscordAsync::new(bot_token); 
    dis_async.start(|event, _| { 
     println!("{:?}", event); 
    }); 
} 

編譯器消息:

Compiling bottest1 v0.1.0 (file:///home/kindlyfire/Documents/dev/rust/bottest1) 
error[E0477]: the type `[[email protected]/discord_async.rs:29:18: 33:5 event_handle:shared_mutex::SharedMutexReadGuard<'_, F>, event:std::sync::Arc<discord::model::Event>, self:&discord_async::DiscordAsync]` does not fulfill the required lifetime 
    --> src/discord_async.rs:29:4 
    | 
29 |   thread::spawn(move || { 
    |   ^^^^^^^^^^^^^ 
    | 
    = note: type must outlive the static lifetime 

而且我Cargo.toml

[package] 
name = "bottest1" 
version = "0.1.0" 
authors = ["kindlyfire"] 

[dependencies] 
discord = "0.7.0" 
colored = "1.4" 
shared-mutex = "0.2" 

我已經看過很多不同的方式來做到這一點,包括在SO上,但我找不到任何工作。

+1

*它不起作用* =>我只是放錯了我的思維閱讀水晶球,你可以稍微更加明確......如包括任何編譯器錯誤?請製作[MCVE](http://stackoverflow.com/help/mcve)。 –

+0

我添加了編譯器錯誤信息和我的'Cargo.toml'。 –

回答

1

您鎖定了互斥鎖,然後嘗試將鎖定的對象移入線程。這是錯誤的方式。您需要克隆Arc並將其移入該線程。

編輯:我沒有測試過這一點,但這樣的事情應該工作:

pub fn start<F>(&self, mut event_handle: F) ->() 
    where F: FnMut(Arc<Event>, Arc<SharedMutex<Discord>>) + Send + 'static 
{ 
    let (mut connection, _) = self.client.read().unwrap().connect().unwrap(); 
    let event_handle = Arc::new(SharedMutex::new(event_handle)); 

    loop { 
     let event = Arc::new(connection.recv_event().unwrap()); 
     let event_handle = event_handle.clone(); 
     let client = self.client.clone(); 

     // Start a thread so we don't block shit 
     thread::spawn(move || { 

      // Match event to actions we want to handle 
      event_handle.read().unwrap()(event, client); 
     }); 
    } 
} 

請注意,我們創建拉姆達外Arc S的克隆,然後裏面使用它們。除了我們沒有克隆的event之外,因爲移動我們所擁有的一個指針可以。這將克隆移入lambda。不過,你可能會擺脫ArcEvent。你沒有任何其他的指針,不需要保持它活着,無論如何它必須是Send(我認爲&T只是Sync,如果TSend)。

如果這不起作用,請更新爲新的編譯器錯誤。

作爲關於術語的一個備註,「句柄」是指引用某個資源的對象。處理事件的函數是「句柄r」。

+0

你能否給我提供實際的固定代碼?在進行多次編輯後,我認爲應該按照您的說法做,但不能正常工作。 2天前我剛開始與Rust合作,所以它很新。 –

+0

添加了一些代碼,但實際上無法嘗試。 –

+0

現在,在'event_handle.read()。unwrap()'上不能借用不可變的借用內容作爲可變的',即使我在函數中的每個'let'之後添加了'mut'。 –