如何创建线程管理器?

时间:2019-10-09 23:06:36

标签: multithreading rust

我有一个要在后台处理的数据流,但是我想创建一个结构或一些函数来管理该流。

在C ++领域,我将创建一个抽象所有这些的类。它会有一个start方法,该方法将初始化数据流并启动一个线程进行处理。它会有一个stop方法来停止处理并加入线程。

但是,这并不是真的Rusty,它甚至在Rust中也不起作用。

示例(Playground

use std::thread;
use std::time::Duration;

struct Handler {
    worker_handle: Option<thread::JoinHandle<()>>,
    stop_flag: bool, // Should be atomic, but lazy for example
}

impl Handler {

    pub fn new() -> Handler {
        let worker_handle = None;
        let stop_flag = true;

        return Handler { worker_handle, stop_flag };
    }

    pub fn start(&mut self) {
        self.stop_flag = false;
        self.worker_handle = Some(std::thread::spawn(move || {
            println!("Spawned");
            self.worker_fn();
        }));
    }

    pub fn stop(&mut self) {
        let handle = match self.worker_handle {
            None => return,
            Some(x) => x,
        };
        self.stop_flag = true;
        handle.join();
    }

    fn worker_fn(&mut self) {
        while !self.stop_flag {
            println!("Working!");
        }
    }
}

fn main() {
    let mut handler = Handler::new();
    handler.start();
    thread::sleep(Duration::from_millis(10000));
    handler.stop();
}

输出:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:20:54
   |
20 |           self.worker_handle = Some(std::thread::spawn(move || {
   |  ______________________________________________________^
21 | |             println!("Spawned");
22 | |             self.worker_fn();
23 | |         }));
   | |_________^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 18:5...
  --> src/main.rs:18:5
   |
18 | /     pub fn start(&mut self) {
19 | |         self.stop_flag = false;
20 | |         self.worker_handle = Some(std::thread::spawn(move || {
21 | |             println!("Spawned");
22 | |             self.worker_fn();
23 | |         }));
24 | |     }
   | |_____^
   = note: ...so that the types are compatible:
           expected &mut Handler
              found &mut Handler
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/main.rs:20:54: 23:10 self:&mut Handler]` will meet its required lifetime bounds
  --> src/main.rs:20:35
   |
20 |         self.worker_handle = Some(std::thread::spawn(move || {
   |                                   ^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

即使我作弊并取消了worker_fn的调用,我仍然无法真正使用JoinHandle,就像我可能希望从C ++领域那样。

error[E0507]: cannot move out of `self.worker_handle.0` which is behind a mutable reference
  --> src/main.rs:27:28
   |
27 |         let handle = match self.worker_handle {
   |                            ^^^^^^^^^^^^^^^^^^ help: consider borrowing here: `&self.worker_handle`
28 |             None => return,
29 |             Some(x) => x,
   |                  -
   |                  |
   |                  data moved here
   |                  move occurs because `x` has type `std::thread::JoinHandle<()>`, which does not implement the `Copy` trait

error: aborting due to previous error

很明显,我不应该使用常规的Rust模型,并且可能不应该使用此策略。

但是我仍然想构建某种 接口,让我可以简单地启动数据流而不必担心管理线程,而且我不确定如何做到这一点的最佳方法。 / p>

所以看来我有两个核心问题。

1)我如何创建一个在线程中运行的函数,该线程接受来自外部源的数据并可以发出安全退出的信号?如果我有一个杀死它的原子布尔,该如何在线程之间共享?

2)完成后如何处理加入线程? stop方法需要清理线程,但是我不知道如何跟踪对该线程的引用。

0 个答案:

没有答案