我正在设计一个为我运行闭包的小结构,我可以将它们设置为停止:
pub fn run(&self, f: Box<dyn Fn()>) {
let should_continue = self.should_continue.clone();
self.run_thread = Some(std::thread::spawn(move || {
while should_continue.load(Ordering::Relaxed) {
//f should run fast so `should_continue` is readed frequently
f();
}
}));
}
如你所见,我正在通过Fn
在一个盒子里,这给了我一个关于盒子不能在线程之间共享的错误。实际上,一旦我将 fn 传递给这个函数,我就不关心它了run
,所以我想将闭包移至此函数,因为我将不再使用它。我无法标记Fn
作为发送,因为f
我实际上要通过的内容并没有实现Send
.
那么,如何才能完全移动闭包呢?
//move this closure to inside of run
self.run(||{});
拥有可构建的复制案例而不是具有随机未提供的依赖项的代码是有用的.
我得到的错误是dyn Fn
不可能是sent线程之间的情况非常不同shared: 虽然有很多事情是做不到的shared (Sync
)在线程之间(它们一次只能从一个线程使用)还有一些东西必须始终保留在其原始线程上。Rc
例如,不是Send
,因为它不是发送一个线程安全的引用计数指针Rc
到不同的线程会破坏其保证,因此这是不允许的。
dyn Fn
是不透明的,除了可多次调用之外,无法真正保证其内部正在执行的操作。因此,就编译器而言,它可能会关闭一些不存在的东西Send
(例如,引用!Sync
类型,或一个Rc
, ...),这意味着编译器假设Fn
isn't Send
either.
解决方案很简单:定义f: Box<dyn Fn() + Send>
,这样内run
您保证该函数实际上可以在线程之间发送;和呼叫者run
如果他们尝试发送无法发送的函数,则会收到错误消息。
run_ok
使用一个简单的闭包,发送它没有问题。run_not_ok
结束于Rc
,因此该函数不会编译(只需取消注释即可查看)。run_ok2
与以下函数相同run_not_ok
使用一个Arc
而不是Rc
,并且编译良好。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)