Asynchronous Rust—如何在一个应用程序中使用同步和异步机箱
我开始编写一个程序,使用crate和crate制作一个webscraping应用程序,我可以查看它的数据。在我花了很长时间构建这个程序之后,我才意识到合并同步和异步编程是个坏主意。我现在要做的是在应用程序打开时运行scraper(最好每小时一次) 现在,刮板直到应用程序关闭后才运行。我尝试使用Tokio的Asynchronous Rust—如何在一个应用程序中使用同步和异步机箱,asynchronous,rust,rust-tokio,rust-async-std,Asynchronous,Rust,Rust Tokio,Rust Async Std,我开始编写一个程序,使用crate和crate制作一个webscraping应用程序,我可以查看它的数据。在我花了很长时间构建这个程序之后,我才意识到合并同步和异步编程是个坏主意。我现在要做的是在应用程序打开时运行scraper(最好每小时一次) 现在,刮板直到应用程序关闭后才运行。我尝试使用Tokio的spawn创建一个单独的线程,在应用程序打开之前启动,但这不起作用,因为Crabler未来没有“发送”特性 我试图制作一个最小的功能程序,如下所示。title\u处理程序的功能不符合预期,但在其
spawn
创建一个单独的线程,在应用程序打开之前启动,但这不起作用,因为Crabler未来没有“发送”特性
我试图制作一个最小的功能程序,如下所示。title\u处理程序
的功能不符合预期,但在其他方面,它很好地说明了我遇到的问题
允许WebScraper在应用程序打开时运行吗?如果是,怎么做
编辑:我尝试使用task::spawn_blocking()
来运行应用程序,但它抛出了大量错误,包括德鲁伊没有实现traitSend
use crabler::*;
use druid::widget::prelude::*;
use druid::widget::{Align, Flex, Label, TextBox};
use druid::{AppLauncher, Data, Lens, WindowDesc, WidgetExt};
const ENTRY_PREFIX: [&str; 1] = ["https://duckduckgo.com/?t=ffab&q=rust&ia=web"];
// Use WebScraper trait to get each item with the ".result__title" class
#[derive(WebScraper)]
#[on_response(response_handler)]
#[on_html(".result__title", title_handler)]
struct Scraper {}
impl Scraper {
// Print webpage status
async fn response_handler(&self, response: Response) -> Result<()> {
println!("Status {}", response.status);
Ok(())
}
async fn title_handler(&self, _: Response, el: Element) -> Result<()> {
// Get text of element
let title_data = el.children();
let title_text = title_data.first().unwrap().text().unwrap();
println!("Result is {}", title_text);
Ok(())
}
}
// Run scraper to get info from https://duckduckgo.com/?t=ffab&q=rust&ia=web
async fn one_scrape() -> Result<()> {
let scraper = Scraper {};
scraper.run(Opts::new().with_urls(ENTRY_PREFIX.to_vec()).with_threads(1)).await
}
#[derive(Clone, Data, Lens)]
struct Init {
tag: String,
}
fn build_ui() -> impl Widget<Init> {
// Search box
let l_search = Label::new("Search: ");
let tb_search = TextBox::new()
.with_placeholder("Enter tag to search")
.lens(Init::tag);
let search = Flex::row()
.with_child(l_search)
.with_child(tb_search);
// Describe layout of UI
let layout = Flex::column()
.with_child(search);
Align::centered(layout)
}
#[async_std::main]
async fn main() -> Result<()> {
// Describe the main window
let main_window = WindowDesc::new(build_ui())
.title("Title Tracker")
.window_size((400.0, 400.0));
// Create starting app state
let init_state = Init {
tag: String::from("#"),
};
// Start application
AppLauncher::with_window(main_window)
.launch(init_state)
.expect("Failed to launch application");
one_scrape().await
}
使用crabler::*;
使用druid::widget::prelude::*;
使用druid::widget::{Align,Flex,Label,TextBox};
使用druid:{AppLauncher,Data,Lens,WindowDesc,WidgetExt};
常量条目\u前缀:[&str;1]=[”https://duckduckgo.com/?t=ffab&q=rust&ia=web"];
//使用WebScraper trait获取带有“.result\uu title”类的每个项目
#[导出(WebScraper)]
#[关于响应(响应处理程序)]
#[在html(“.result\u title”,title\u handler)”上]
结构刮板{}
impl刮刀{
//打印网页状态
异步fn响应\u处理程序(&self,response:response)->结果{
println!(“状态{}”,response.Status);
好(())
}
异步fn title\u处理程序(&self,\u:Response,el:Element)->Result{
//获取元素的文本
设title_data=el.children();
让title_text=title_data.first().unwrap().text().unwrap();
println!(“结果为{}”,标题为文本);
好(())
}
}
//运行scraper从中获取信息https://duckduckgo.com/?t=ffab&q=rust&ia=web
异步fn one_scrape()->结果{
设scraper=scraper{};
scraper.run(Opts::new()。带有\u URL(条目\u前缀.to\u vec())。带有\u线程(1))。等待
}
#[衍生(克隆、数据、镜头)]
结构初始化{
标签:字符串,
}
fn build_ui()->impl小部件{
//搜索框
让l_search=Label::new(“search:”);
让tb_search=TextBox::new()
.带有占位符(“输入要搜索的标记”)
.lens(Init::tag);
let search=Flex::row()
.带子对象(l_搜索)
.有子女(tb_搜索);
//描述UI的布局
let layout=Flex::column()
.有子女(搜索);
对齐::居中(布局)
}
#[async_std::main]
异步fn main()->结果{
//描述主窗口
让main\u window=WindowDesc::new(build\u ui())
.title(“title Tracker”)
.窗口大小((400.0400.0));
//创建启动应用程序状态
让init_state=init{
tag:String::from(“#”),
};
//启动应用程序
AppLauncher::带_窗口(主_窗口)
.启动(初始状态)
.expect(“未能启动应用程序”);
等一等
}
使用东京时,您可以使用。其他异步框架提供类似的功能。尽管spawn\u blocking
旨在与终止同步任务进行接口。要拥有一个主要独立于异步运行时的长时间运行线程(这里的情况似乎是这样?还不完全清楚),通常建议使用常规的spawn
。