rust - 在线程内使用闭包

标签 rust

我正在尝试在线程中使用闭包,但经过 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 `[closure@src/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 上,但我找不到任何可行的方法。

最佳答案

您锁定互斥体,然后尝试将锁定的对象移入线程。那是错误的方法。您需要克隆 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);
        });
    }
}

请注意,我们在 lambda 外部创建了 Arc 的克隆,然后在内部使用它们。除了 event,我们不克隆它,因为我们可以移动我们拥有的一个指针。这会将克隆移动到 lambda 中。不过,您可能可以摆脱 Event 周围的 Arc。你没有任何其他指向它的指针,不需要让它保持事件状态,而且它必须是 Send 无论如何(我认为 &T 只是 如果 TSend,则同步

如果这不起作用,请使用新的编译器错误进行更新。

作为术语的旁注,“句柄”是指代某些资源的对象。处理事件的函数是“handler”。

关于rust - 在线程内使用闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41533162/

相关文章:

rust - 为什么不能在同一结构中存储值和对该值的引用?

rust - 让GtkComboBox条目为Pixbuf或String

stream - 一旦其中一个底层流耗尽,就使流组合耗尽

rust - 找不到命令: wrangler

rust - 为什么可以在比赛中使用以前未声明的名称?

vector - 根据索引在循环中删除向量的元素

Rust solana 构建错误 : no such subcommand: +bpf

c++ - 使用 gcc 链接从 Rust 编译的动态库

rust - impl 上的第一个显式生命周期说明符是什么意思?

rust - 为什么 Rust 不推断这个闭包的返回类型?