在 Rust 中访问线程内的 self 方法

Cas*_*per 7 multithreading rust

我想将self结构对象传播到线程中,然后调用其time_tick()方法来增加 HMS 时间。

pub fn start(&mut self) {
    self.acti = true;   // the time tick is activated now...
    thread::spawn(move || {
        let local_self: *mut Self = self;   // this self live in the thread
        loop {
            thread::sleep(Duration::from_secs(1));  // wait for 1 sec
            if (*local_self).acti == true { (*local_self).time_tick(); }    
            (*local_self).print_time();  // for debug
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

我收到错误消息:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/hmstimer/mod.rs:42:17
   |
42 |           thread::spawn(move || {
   |  _______________________^
43 | |             let local_self: *mut Self = self;   // this self live in the thread
44 | |             loop {
45 | |                 thread::sleep(Duration::from_secs(1));    // wait for 1 sec
...  |
48 | |             }
49 | |         });
   | |_________^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 40:2...
  --> src/hmstimer/mod.rs:40:2
   |
40 |       pub fn start(&mut self) {
   |  _____^
41 | |         self.acti = true;    // the time tick is activated now...
42 | |         thread::spawn(move || {
43 | |             let local_self: *mut Self = self;   // this self live in the thread
...  |
49 | |         });
50 | |     }
   | |_____^
   = note: ...so that the types are compatible:
           expected &mut hmstimer::HMSTimer
              found &mut hmstimer::HMSTimer
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/hmstimer/mod.rs:42:17: 49:7 self:&mut hmstimer::HMSTimer]` will meet its required lifetime bounds
Run Code Online (Sandbox Code Playgroud)

但好像about方法不太合适。完成任务的最佳实践是什么?

Fra*_*gné 6

您无法传递捕获可变引用的闭包thread::spawnthread::spawn需要函数为'static,这意味着它要么不捕获任何借用,要么所有借用都是'static。这是因为在引用对象被删除后,线程可以继续运行。

如果调用后不需要self在原始线程中使用start,那么可以只self按值传递。

pub fn start(self) {
    self.acti = true;
    thread::spawn(move || {
        loop {
            thread::sleep(Duration::from_secs(1));
            if self.acti == true { self.time_tick(); }    
            self.print_time();
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

否则,您将需要使用Arc来让两个线程共享 的所有权Self,以及MutexRwLock来同步线程间的读取和写入。

// note: this is not a method anymore;
// invoke as `HMSTimer::start(arc.clone());`
pub fn start(this: Arc<Mutex<Self>>) {
    this.lock().expect("mutex is poisoned").acti = true;
    thread::spawn(move || {
        loop {
            thread::sleep(Duration::from_secs(1));
            let lock = this.lock().expect("mutex is poisoned");
            if lock.acti == true { lock.time_tick(); }    
            lock.print_time();
            // `lock` is dropped here, unlocking the mutex
        }
    });
}
Run Code Online (Sandbox Code Playgroud)