我尝试使用Future.rs在单独的进程中管理某些任务。我看到如何等待每个创造的未来以及如何一个接一个地处理它们,但是我无法在执行期间轮询未来以了解它的状态。我总是有错误:
线程'主要'惊慌失措没有任务正在运行'
我希望在将来的处理过程中做一些事情,直到它完成。也许我没有以正确的方式使用它?我设法通过使用频道使其工作,但我认为应该可以轮询未来以及何时准备好获得结果。 我用来测试它的代码是:
fn main() {
println!("test future");
let thread_pool = CpuPool::new(4);
let mut future_execution_list = vec![];
let mutex = Arc::new(AtomicUsize::new(0));
//create the future to process
for _ in 0..10 {
let send_mutex = mutex.clone();
let future = thread_pool.spawn_fn(move || {
//Simulate long processing
thread::sleep(time::Duration::from_millis(10));
let num = send_mutex.load(Ordering::Relaxed);
send_mutex.store(num + 1, Ordering::Relaxed);
let res: Result<usize, ()> = Ok(num);
res
});
future_execution_list.push(future);
}
// do the job
loop {
for future in &mut future_execution_list {
match future.poll() {
Ok(Async::NotReady) => (), //do nothing
Ok(Async::Ready(num)) => {
//update task status
println!(" future {:?}", num);
}
Err(_) => {
//log error and set task status to err
()
}
};
}
//do something else
}
}
所以在Shepmaster回答之后我完成了我的问题。你的言论非常有趣,但我仍然无法找到解决问题的办法。我将添加一些关于我的问题的信息。我想在一个可以一次管理多个任务的自动化上安排任务。存在一个循环,其中管理事件并计算任务调度。当任务被安排时,它会产生。当任务结束时,完成新的调度。在任务执行期间,管理事件。一个speudo代码可以是:
loop {
event.try_recv() { ...} //manage user command for exemple
if (schedule) {
let tasks_to_spawn = schedule_task();
let futures = tasks_to_spawn.map(|task| {
thread_pool.spawn_fn( ....)});
let mut one = future::select_all(futures);
while let Ok((value, _idx, remaining)) = one.wait() {..} //wait here
}
//depend on task end state and event set schedule to true or false.
}
我可以在未来联合调度和任务,如:
let future = schedule.and_them(|task| execute_task);
但是我仍然需要等待第一个任务的执行结束。 我可以把所有事情都放在未来(事件管理,日程安排,任务),然后等待你提出的第一个结束。我尝试但我没有看到如何使用不同的项目和错误类型制作未来的vec。有了这个概念,我必须在线程之间管理更多数据。事件管理和调度不必在不同的线程中执行。
我看到另一个问题,select_all取得了vec的所有权。如果在执行另一个任务期间必须对新任务进行调整,我该如何更改vec并添加新的未来?
不知道你是否有一个简单的解决方案。我认为在使用isDone()之类的方法执行期间获取未来状态很简单,而不必等待。也许是它的计划,我没有看到关于那个的公关。 如果你有一个简单的解决方案,那将是很好的,否则我会重新考虑我的观念。
答案 0 :(得分:2)
要轮询Future
,您必须拥有Task
。要获得Task
,您可以在传递给Future
的{{1}}中进行投票。如果你像这样重写你的例子的futures::executor::spawn()
:
loop
它运行。
至于为什么 futures::executor::spawn(futures::lazy(|| {
// existing loop goes here
})).wait_future();
只能在任务中进行轮询,我相信轮询可以调用Future
。
答案 1 :(得分:0)
我想在将来的处理中做点什么
据我了解,那就是期货 - 可以并行发生的事情。如果你想做别的事情,那就再做一个未来并把它扔进去!
你基本上已经这样做了 - 你的每个主题都是&#34;做其他事情&#34;。
调查未来以及何时准备好获得结果
使用future::select_all
,您可以组合多个期货,并获得最先完成的任何结果。然后由您决定等待下一个。
一种可能的实施方式:
extern crate rand;
extern crate futures;
extern crate futures_cpupool;
use rand::Rng;
use futures::{future, Future};
use futures_cpupool::CpuPool;
use std::{thread, time};
fn main() {
let thread_pool = CpuPool::new(4);
let futures = (0..10).map(|i| {
thread_pool.spawn_fn(move || -> Result<usize, ()> {
let mut rng = rand::thread_rng();
// Simulate long processing
let sleep_time = rng.gen_range(10, 100);
let sleep_time = time::Duration::from_millis(sleep_time);
for _ in 0..10 {
println!("Thread {} sleeping", i);
thread::sleep(sleep_time);
}
Ok(i)
})
});
let mut one = future::select_all(futures);
while let Ok((value, _idx, remaining)) = one.wait() {
println!("Future #{} finished", value);
if remaining.is_empty() {
break;
}
one = future::select_all(remaining);
}
}
在致电wait
期间,同时发生了多项事情!这可以通过交错输出看出:
Thread 2 sleeping
Thread 0 sleeping
Thread 3 sleeping
Thread 1 sleeping
Thread 3 sleeping
Thread 0 sleeping
Thread 1 sleeping
Thread 2 sleeping
Thread 3 sleeping
您可以通过将每个线程的休眠时间设置为1秒并对整个程序进行计时来验证事情是否并行发生。由于有10个期货,需要1秒,平行度为4,整个程序需要3秒才能运行。
奖金代码审核:
fetch_add
。SeqCst
。Vec
而不是在循环内推入它。这样可以实现更优化的分配。Vec
接受任何可以转换为迭代器的内容,因此根本不需要select_all
。