Asynchronous 如何在不等待的情况下调查未来状态?

Asynchronous 如何在不等待的情况下调查未来状态?,asynchronous,rust,future,Asynchronous,Rust,Future,我正在尝试使用Future.rs在单独的流程中管理一些任务。我知道如何等待每个已创建的未来,以及如何一个接一个地处理它们,但我无法在未来执行期间轮询未来以了解其状态。我总是有这样的错误: 线程“main”在“当前没有任务正在运行”时惊慌失措 我想在以后的处理过程中做一些事情,直到它完成。也许我用得不对?我设法通过一个渠道让它发挥作用,但我认为应该可以对未来进行民意调查,并在它准备好的时候得到结果。 我用来测试它的代码是: fn main() { println!("test future

我正在尝试使用Future.rs在单独的流程中管理一些任务。我知道如何等待每个已创建的未来,以及如何一个接一个地处理它们,但我无法在未来执行期间轮询未来以了解其状态。我总是有这样的错误:

线程“main”在“当前没有任务正在运行”时惊慌失措

我想在以后的处理过程中做一些事情,直到它完成。也许我用得不对?我设法通过一个渠道让它发挥作用,但我认为应该可以对未来进行民意调查,并在它准备好的时候得到结果。 我用来测试它的代码是:

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);
        }
    }