我想在異步背景關系中多次重復某個用戶提供的功能。因此,我想到了一個非異步閉包,它產生可以被消費/等待的期貨。
一個最小的可重現示例如下:
let counter = Arc::new(AtomicU64::new(0));
let counter_closure = counter.clone();
let future_producer = move || async {
counter_closure.fetch_add(1, Ordering::SeqCst);
};
但這會導致此錯誤
562 | let future_producer = move || async {
| _______________________________-------_^
| | | |
| | | return type of closure `impl Future<Output = ()>` contains a lifetime `'2`
| | lifetime `'1` represents this closure's body
563 | | counter_closure.fetch_add(1, Ordering::SeqCst);
564 | | };
| |_________^ returning this value requires that `'1` must outlive `'2`
我怎么解決這個問題?
uj5u.com熱心網友回復:
問題是閉包擁有counter_closure
,但閉包回傳的期貨只參考閉包擁有的這個值。閉包的簽名沒有辦法表達這一點。它類似于“擁有迭代器”的問題——比如Iterator
特征如何不允許表達迭代器分配與其自身生命周期相關的參考的情況,可以在對閉包的參考上呼叫的閉包特征家族(Fn
和FnMut
) 沒有辦法表示從閉包回傳的值是從閉包本身借用的。
如果編譯器允許它編譯,則可以通過洗掉閉包來創建釋放后使用的情況,而它之前回傳的期貨仍然存在。這會counter_closure
在它仍然被借來的時候摧毀。
您可以通過在塊之前的counter_closure
每次呼叫閉包時克隆閉包擁有的閉包來解決此問題,并將此克隆移至未來:async
async move
let counter = Arc::new(AtomicU64::new(0));
let counter_closure = counter.clone();
let future_producer = move || {
let counter_inner = counter_closure.clone();
async move {
counter_inner.fetch_add(1, Ordering::SeqCst);
}
};
通過賦予 future 自己的 ,這將 future 的生命周期與閉包解耦Arc
。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/508495.html