Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 你如何使用遗嘱执行人来解决未来的问题?_Rust - Fatal编程技术网

Rust 你如何使用遗嘱执行人来解决未来的问题?

Rust 你如何使用遗嘱执行人来解决未来的问题?,rust,Rust,这段代码令人恐慌: extern crate futures; use futures::Future; use futures::future; use futures::sync::oneshot::{channel, Canceled}; use std::thread; use std::time::Duration; fn maybe_oneday() -> Box<Future<Item = i32, Error = Canceled>> {

这段代码令人恐慌:

extern crate futures;

use futures::Future;
use futures::future;
use futures::sync::oneshot::{channel, Canceled};
use std::thread;
use std::time::Duration;

fn maybe_oneday() -> Box<Future<Item = i32, Error = Canceled>> {
    let (s, r) = channel::<i32>();
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(100));
        let _ = s.send(100);
    });
    return Box::new(r);
}

fn main() {
    let foo = maybe_oneday();
    let mut wrapper = foo.then(|x| {
        match x {
            Ok(v) => {
                println!("GOT: {:?}", v);
                future::ok::<i32, Canceled>(v)
            },
            Err(y) => {
                println!("Err: {:?}", y);
               future::err::<i32, Canceled>(y)
            }
        }
    });

    // wrapper.wait() <-- Works, but blocks
    let _ = wrapper.poll(); // <-- Panics
}
大概我必须使用某种执行者来授权任务解决;但是怎么做呢

文档引用了我的执行者,但是,链接断开了吗


我从哪里获得执行器?

一般来说,
tokio
futures
被设计为异步原语,而不是一般的任务系统

也就是说,如果您希望异步分派多个任务并“触发并忘记”它们,请使用
thread::spawn

如果要在单个线程中运行多个任务,则
Future
是用于在该线程中阻塞的正确原语,直到解决未来链

在这种情况下,我的问题没有真正意义,因为我认为
Future
应该表示类似于C#中的
Task
;也就是说,对线程池进行动态调度,以便稍后执行任务,并且在该任务解决时可能会发生连锁操作;这些任务依次在不同的线程中执行

这不是
futures
tokio
支持的模型

然而,为了激怒反对者,我在这里补充了我所问实际问题的答案:

答案是,它实现了许多基本的执行器,包括一个用于任意任务的执行器

见:

具体而言:

您可以这样使用它们:

extern crate futures;
extern crate tokio;

use futures::Future;
use futures::future;
use futures::future::Executor;
use tokio::executor::current_thread;
use futures::sync::oneshot::{channel, Canceled};
use tokio::executor::current_thread::task_executor;
use std::thread;
use std::time::Duration;
use std::sync::mpsc::Sender;
use std::sync::mpsc;
use std::sync::{Arc, Mutex};

struct RemoteReactor {
    channel: Sender<Box<Future<Item=(), Error=()> + Send + 'static>>
}

impl RemoteReactor {
    fn new() -> RemoteReactor {
        let (send, recv) = mpsc::channel::<Box<Future<Item=(), Error=()> + Send + 'static>>();
        let threadsafe_recv = Arc::new(Mutex::new(recv));
        thread::spawn(move || {
            let reader = threadsafe_recv.lock().unwrap();
            current_thread::run(|_| {
                loop {
                    let future = reader.recv().unwrap();
                    println!("Got a future!");
                    task_executor().execute(future).unwrap();
                    break;
                }
            });
        });
        return RemoteReactor {
            channel: send
        };
    }

    fn execute(&self, future: Box<Future<Item=(), Error=()> + Send + 'static>) {
        self.channel.send(future).unwrap();
    }
}

fn maybe_oneday() -> Box<Future<Item=i32, Error=Canceled> + Send + 'static> {
    let (s, r) = channel::<i32>();
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(100));
        let _ = s.send(100);
    });
    return Box::new(r);
}

fn main() {
    let foo = maybe_oneday();
    let wrapper = Box::new(foo.then(|x| {
        match x {
            Ok(v) => {
                println!("GOT: {:?}", v);
                future::ok::<(), ()>(())
            }
            Err(y) => {
                println!("Err: {:?}", y);
                future::err::<(), ()>(())
            }
        }
    }));

    let reactor = RemoteReactor::new();
    reactor.execute(wrapper);

    println!("Waiting for future to resolve");
    thread::sleep(Duration::from_millis(200));

    println!("All futures are probably resolved now");
}

如果您详细说明为什么要使用
.poll
而不是使用
.wait
进行阻止,可能会有所帮助。一般来说,未来的想法是避免不断地进行轮询以查看是否成功。@loganfsmyth好吧,如果没有
poll
,您如何做到这一点<代码>线程::生成(| |{x.wait();})?我以为这是遗嘱执行人应该解决的问题。如果有其他的方法,我很乐意用另一种方法。我只想阻止当前线程。我想我最近读了一些关于一个执行器的文章,该执行器将分配给它的所有任务在一个线程上进行多路复用,但我现在找不到它?我想这很难说,因为你的代码片段只有一个未来,所以没有其他可以阻止的东西会影响任何事情。也许一个扩展的例子可以说明某些被阻止的东西会导致问题,这会有所帮助吗?归根结底,阻塞是执行者的工作,因为同步阻塞值基本上拥有它所管理的所有任务的执行。因此,如果您使用Tokio,它仍然是阻塞的:我的观点是,如果不理解为什么避免阻塞主线程是您的目标,那么就不清楚任何给定的答案是否适合您的用例。如果您没有阻塞主线程,您是否计划在自己的代码中有一个循环来不断轮询?如果你这样做而不是阻止,是什么推动了这次投票?例如,如果一个未来会花费未知的时间,那么花整个时间检查它是否完成并不是真正有效的。很好,你得到了答案,但仍然不清楚为什么这个特定的答案会解决你的问题,因为
current_thread::run
仍然会阻塞主线程。给出您的示例代码,它基本上与您所说的不想要的
.wait
方法相同。无论如何,很高兴在这里结束讨论。游乐场从crates.io(有文档记录)中获取下载量最多的100个板条箱。由于东京最近才出版了一些有用的东西,它还没有达到足够的受欢迎程度,无法被带到游乐场。
extern crate futures;
extern crate tokio;

use futures::Future;
use futures::future;
use futures::future::Executor;
use tokio::executor::current_thread;
use futures::sync::oneshot::{channel, Canceled};
use tokio::executor::current_thread::task_executor;
use std::thread;
use std::time::Duration;
use std::sync::mpsc::Sender;
use std::sync::mpsc;
use std::sync::{Arc, Mutex};

struct RemoteReactor {
    channel: Sender<Box<Future<Item=(), Error=()> + Send + 'static>>
}

impl RemoteReactor {
    fn new() -> RemoteReactor {
        let (send, recv) = mpsc::channel::<Box<Future<Item=(), Error=()> + Send + 'static>>();
        let threadsafe_recv = Arc::new(Mutex::new(recv));
        thread::spawn(move || {
            let reader = threadsafe_recv.lock().unwrap();
            current_thread::run(|_| {
                loop {
                    let future = reader.recv().unwrap();
                    println!("Got a future!");
                    task_executor().execute(future).unwrap();
                    break;
                }
            });
        });
        return RemoteReactor {
            channel: send
        };
    }

    fn execute(&self, future: Box<Future<Item=(), Error=()> + Send + 'static>) {
        self.channel.send(future).unwrap();
    }
}

fn maybe_oneday() -> Box<Future<Item=i32, Error=Canceled> + Send + 'static> {
    let (s, r) = channel::<i32>();
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(100));
        let _ = s.send(100);
    });
    return Box::new(r);
}

fn main() {
    let foo = maybe_oneday();
    let wrapper = Box::new(foo.then(|x| {
        match x {
            Ok(v) => {
                println!("GOT: {:?}", v);
                future::ok::<(), ()>(())
            }
            Err(y) => {
                println!("Err: {:?}", y);
                future::err::<(), ()>(())
            }
        }
    }));

    let reactor = RemoteReactor::new();
    reactor.execute(wrapper);

    println!("Waiting for future to resolve");
    thread::sleep(Duration::from_millis(200));

    println!("All futures are probably resolved now");
}
rustc 1.24.0 (4d90ac38c 2018-02-12)

$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.1 secs
     Running `target\debug\hello_future.exe`
Waiting for future to resolve
Got a future!
GOT: 100
All futures are probably resolved now