我一直在尝试从postgres迁移到时雄_postgres,但是遇到了一些异步问题。
use scraper::Html;
use std::sync::Arc;
use tokio::sync::Mutex;
use tokio::task;
struct Url {}
impl Url {
fn scrapped_home(&self, symbol: String) -> Html {
let url = format!(
"https://finance.yahoo.com/quote/{}?p={}&.tsrc=fin-srch", symbol, symbol
);
let response = reqwest::blocking::get(url).unwrap().text().unwrap();
scraper::Html::parse_document(&response)
}
}
# [derive(Clone)]
struct StockData {
symbol: String,
}
# [tokio::main]
async fn main() {
let stock_data = StockData { symbol: "".to_string() };
let url = Url {};
let mut uri_test: Arc<Mutex<Html>> = Arc::new(Mutex::from(url.scrapped_home(stock_data.clone().symbol)));
let mut uri_test_closure = Arc::clone(&uri_test);
let uri = task::spawn_blocking(|| {
uri_test_closure.lock()
});
}
而不将互斥锁置于
url.scrapped_home(stock_data.clone().symbol)),
我会得到运行时不能在不允许阻塞的上下文中丢弃的错误,所以我在spawn_blocking中放入。然后我得到Cell不能在线程之间安全共享的错误。从我所能收集的来看,这是因为Cell不是“它的同步。然后我在互斥体中 Package 。另一方面,这会抛出Cell不能在线程之间安全共享"。
现在,这是因为它包含了对Cell的引用,因此不是内存安全的吗?如果是这样,我需要为Html实现Sync吗?如何实现?
Html是从刮刀板条箱。
最新消息:
抱歉,出现错误。
error: future cannot be sent between threads safely
--> src/database/queries.rs:141:40
|
141 | let uri = task::spawn_blocking(|| {
| ________________________________________^
142 | | uri_test_closure.lock()
143 | | });
| |_________^ future is not `Send`
|
= help: within `tendril::tendril::NonAtomic`, the trait `Sync` is not implemented for `Cell<usize>`
note: required by a bound in `spawn_blocking`
--> /home/a/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.20.1/src/task/blocking.rs:195:12
|
195 | R: Send + 'static,
| ^^^^ required by this bound in `spawn_blocking`
最新消息:
按要求添加货物:
[package]
name = "reprod"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
reqwest = { version = "0.11", features = ["json", "blocking"] }
tokio = { version = "1", features = ["full"] }
tokio-postgres = "0"
scraper = "0.12.0"
更新:添加了原始同步代码:
fn main() {
let stock_data = StockData { symbol: "".to_string() };
let url = Url {};
url.scrapped_home(stock_data.clone().symbol);
}
更新:多亏了Kevin,我才能让它工作起来。正如他指出的Html
既不是Send
也不是Sync
。这个part of the Rust lang doc帮助我理解了消息传递是如何工作的。
pub fn scrapped_home(&self, symbol: String) -> Html {
let (tx, rx) = mpsc::channel();
let url = format!(
"https://finance.yahoo.com/quote/{}?p={}&.tsrc=fin-srch", symbol, symbol
);
thread::spawn(move || {
let val = reqwest::blocking::get(url).unwrap().text().unwrap();
tx.send(val).unwrap();
});
scraper::Html::parse_document(&rx.recv().unwrap())
}
后来我有了一些顿悟,并让它与时雄一起工作,没有消息传递,以及
pub async fn scrapped_home(&self, symbol: String) -> Html {
let url = format!(
"https://finance.yahoo.com/quote/{}?p={}&.tsrc=fin-srch", symbol, symbol
);
let response = task::spawn_blocking(move || {
reqwest::blocking::get(url).unwrap().text().unwrap()
}).await.unwrap();
scraper::Html::parse_document(&response)
}
我希望这能帮助到一些人。
1条答案
按热度按时间wkftcu5l1#
这一点现在更清楚地说明了:您试图跨越线程边界返回一个
tokio::sync::MutexGuard
。当您调用此函数时:uri_test_closure.lock()
调用(tokio::sync::Mutex::lock()
)没有分号,这意味着它返回的对象是调用的结果。但是,您不能跨越线程边界返回MutexGuard
。我建议您仔细阅读链接的
lock()
调用,以及blocking_lock()
等。我不确定您在这里调用
task::spawn_blocking
的意义,如果您试图说明某个东西的用例,那是不可能的。编辑:
Html
既是!Send
又是!Sync
,这意味着您甚至不能将其封装在Arc<Mutex<Html>>
或Arc<Mutex<Optional<Html>>>
或其他类型的线程中。而不是作为一个“整体”的对象。更多的详细信息请参见rust用户论坛上的this post。但是无论你 Package 的是什么,* 必须 * 是Send
,且该结构体显式为 not。因此,如果一个类型是
Send
和!Sync
,您可以 Package 在一个Mutex
和一个Arc
中,但是如果它是!Send
,您就被束缚住了,需要使用消息传递或其他同步机制。