Asynchronous 如何在不等待的情况下调查未来状态?
我正在尝试使用Future.rs在单独的流程中管理一些任务。我知道如何等待每个已创建的未来,以及如何一个接一个地处理它们,但我无法在未来执行期间轮询未来以了解其状态。我总是有这样的错误: 线程“main”在“当前没有任务正在运行”时惊慌失措 我想在以后的处理过程中做一些事情,直到它完成。也许我用得不对?我设法通过一个渠道让它发挥作用,但我认为应该可以对未来进行民意调查,并在它准备好的时候得到结果。 我用来测试它的代码是:Asynchronous 如何在不等待的情况下调查未来状态?,asynchronous,rust,future,Asynchronous,Rust,Future,我正在尝试使用Future.rs在单独的流程中管理一些任务。我知道如何等待每个已创建的未来,以及如何一个接一个地处理它们,但我无法在未来执行期间轮询未来以了解其状态。我总是有这样的错误: 线程“main”在“当前没有任务正在运行”时惊慌失措 我想在以后的处理过程中做一些事情,直到它完成。也许我用得不对?我设法通过一个渠道让它发挥作用,但我认为应该可以对未来进行民意调查,并在它准备好的时候得到结果。 我用来测试它的代码是: fn main() { println!("test future
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
}
}
我可以在未来将计划和任务结合起来,如:
let future = schedule.and_them(|task| execute_task);
但是我仍然需要等待第一个任务的执行结束。
我可以把一切放在未来(活动管理、日程安排、任务),然后等待第一个像你建议的那样结束。我试过了,但我不知道如何使用不同的项目和错误类型来创建未来的vec。有了这个概念,我必须在线程之间管理更多的数据。事件管理和调度不必在不同的线程中执行
我看到另一个问题,选择所有人都拥有vec。如果在执行另一个任务期间必须安排新任务,我如何更改vec并添加新的未来
不知道你是否有一个简单的解决方案。我认为,在执行过程中,使用类似isDone()的方法而不必等待,就可以很容易地获得未来的状态。也许这是有计划的,我没有看到关于这个的公关。
如果你有一个简单的解决方案,那就太好了,否则我会重新考虑我的想法 要轮询
未来
您必须有一个任务
。要获取任务
,您可以在传递给futures::executor::spawn()
的未来
中进行轮询。如果您像这样重新编写示例的循环
:
futures::executor::spawn(futures::lazy(|| {
// existing loop goes here
})).wait_future();
它运行
至于为什么只能在任务中轮询未来
,我相信这是因为轮询可以调用任务::Unpark
我想在以后的处理过程中做点什么
据我所知,这就是未来——可以并行发生的事情。如果你想做其他的事情,那就创造另一个未来,把它投入其中吧
你基本上已经在做这个了——你的每个线程都在“做其他的事情”
调查未来,当它准备好的时候得到结果
使用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);
}
}
您可以通过将每个线程的睡眠时间设置为1秒并对整个程序计时来验证事情是否并行发生。因为有10个未来,需要1秒,并行度为4,所以整个程序运行需要3秒
奖金代码审查:
fetch\u add
SeqCst
Vec
中,而不是将其推入循环中。这允许更优化的分配Vec
,因为select\u all
接受任何可以转换为迭代器的内容李>
有99.9%的几率你不想以那种方式使用原子变量。相反,你想要
fetch\u add
,而绝大多数人不想要轻松的
排序。你的权利,我只是复制/粘贴一些代码,以表明我想从未来的执行中得到一个结果,这取决于其他期货的执行。这是正确的。提问者应该从一开始就提出一个好的问题,包括任何相关的细节。所以我不能改变我的问题(我理解为什么),我不能回答答案。我的答复被删除了。那么,我如何才能对最初的问题进行更深入的解释,特别是当他们提到答案时,使用评论?我真的不习惯这种流程。通常情况下,讨论的流程允许跟随进化。下次当我有复杂的问题时,我会使用Reddit或其他论坛。感谢您的评论和帮助,以改善我对stackoverflow的使用。您完全可以回答。这就是每个答案下面的评论的目的(就像这个问题下面的评论一样)。堆栈溢出是一个问答网站。这不适合每个人的风格,没关系,或者是讨论防锈代码的好地方。
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);
}
}