在特定线程中运行异步函数

3
我想在单独的线程上运行特定的长时间运行的函数(执行数据库查询)。但是,假设基础数据库引擎一次只允许一个连接,并且连接结构体不是Sync(我认为至少后者对于diesel是正确的)。
我的解决方案是有一个单独的线程(而不是线程池),所有数据库工作都在其中完成,并在主线程活动时一直运行。我知道如何通过通道传递消息来实现这一点,但是需要相当多的样板代码(例如显式发送函数参数等)。
在rust中(可能包括tokio和nightly中的新异步/等待符号),是否有更直接的方法来实现类似这样的东西?
我希望能够按照下列方式进行操作:
let handle = spawn_thread_with_runtime(...);

let future = run_on_thread!(handle, query_function, argument1, argument2);

这里的query_function指的是一个可以立即返回future并在其他线程中执行工作的函数。

可以使用Rust nightly和外部crate或宏。

1个回答

1
如果使用外部包是一个选项,我建议看一下 actix,这是一个 Rust 并发框架。
使用它可以在一个独立的线程中生成一个 Actor,该 Actor 实际上拥有与数据库的连接。然后它可以监听消息,根据这些消息执行工作/查询,并返回同步结果或 futures。
它在消息传递、生成等方面处理了大部分样板代码,并提供了更高层次的抽象。
在 actix 文档中还有一个 Diesel 示例,听起来非常接近您所考虑的用例。

谢谢您的建议。在这里,actix似乎很有用,尽管我曾希望有一种更透明的实现方式。也许我会考虑编写一些宏来实现,但目前看来这已经足够了。 - mrspl
我采用的另一种方法(虽然没有在Diesel中尝试过)是使用r2d2和futures。我将使用r2d2池句柄创建一个新的future,该future将委托获取/返回连接给r2d2,因此即使有单个连接和多个futures,也不需要进行消息传递/锁定等操作。 - Dave Challis
那么你在 r2d2 中基本上将池大小限制为 1? - mrspl
@mrspl 如果这是一个要求的话,看一下Diesel r2d2模块(我猜只是r2d2的重新导出)的测试用例,它们有一个池大小为2的测试用例:https://docs.diesel.rs/src/diesel/r2d2.rs.html#165 - Dave Challis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接