如何将impl Fn Trait对象传递到多个线程中,就像使用线程池一样



(Rust编译器1.64.0版(我想做的是:我想为一些Minecraft式的世界创造某种世界生成过程。因此,我希望能够将一个函数传递给某个World生成器,并在每个块上执行这个函数。到目前为止,这个过程是单线程的,我想至少对块生成过程进行多线程处理,因为这不需要同步,所以这是一件对多处理器非常友好的事情

现在,我有一个函数generate_world(self: &mut Self, generator : impl Fn(isize, isize, isize) ->BlockType) ->(){}

这个函数在中间有一个很大的for循环,它在每次需要时都会调用函数生成器,并且是单线程的。

我现在决定使用线程池机箱。这允许我创建一个pool: ThreadPool,并调用pool.execute(move ||{});来执行作业(例如,首先进行一些准备,然后生成一个块,或者更确切地说,一次生成一个完整的条纹(。

我还遇到的是,生成器在第一次调用时就被移到了线程函数中,但这(显然(已经通过装箱和弧形处理得到了修复

现在,我当然试着把生成器函数放在那里,并被正确地警告我应该在生成器函数上指定+Send和+Sync,我毫不犹豫地做到了。现在的问题是,我还应该指定一个生存期,建议是:"静态"。不幸的是,我的程序结构不允许我这样做,因为函数中的一些组件的寿命确实受到主函数一部分的限制。

我该怎么做才能让它发挥作用?我知道在整个生成过程完成之前,该功能不会超出范围。

我对铁锈还很陌生,所以我可能(也可能(忘记了文档中隐藏的许多概念。我很确定,有一种非常干净、非常像铁锈的方法来解决这个问题,但我的思维停留在C++思维中。:(

不幸的是,我的程序结构不允许我这样做,因为函数中的一些组件的寿命确实受到主函数一部分的限制。

这是您需要更改的部分。更改程序的那些部分,这样就不会从main()中借用任何内容。

  • 对常量数据使用consts或static变量。

  • 使用Arc而不是&来引用启动时计算的共享数据。

  • 或者,如果绝对必要(例如,当数据不是常量并且必须在Copy需求中引用时(,并且您在启动时只会执行一次,则使用Box::leak(Box::new(data))获取对某些数据的&'static引用,这些数据以后将永远不会被释放。除了只计算一次的数据外,您不能将其用于任何事情,因为这样您的程序将在真正意义上泄漏内存,并不断增长。

使用作用域的线程可以将借用的数据传递给线程,但这种方法需要对线程进行特殊控制,并且不适用于GUI事件循环或线程池等本身没有特定作用域的情况。


进一步解释:

为什么我需要传递具有静态生存期的东西?线程不会活那么久,所有的东西都直接连接在下面。

简单:借用检查器不理解线程连接。它只查看非常特定的编译时信息;当调用这个join()函数时,线程必须在"退出"之后退出;不是它能进行的那种推理。从广义上讲,借用检查器只关心没有发生的事情("此引用在生命周期之外不使用"(,而不能使用发生的事情,比如";CCD_ 13称为";,作为该计划健全的证据。

我上面提到的"作用域线程"是一种使停止线程对借用检查器来说是可以理解的方法——通过使其看起来像退出函数作用域,借用检查器确实将其理解为借用肯定结束的原因。

最新更新