主线程是否等待从并发效果返回的纤程?

问题描述

我们正在做我们想在一个单独的线程中运行的 IO 操作,主线程不应该等待这个操作。

def seperateThread(action: F[Unit]): F[Unit]
  ConcurrentEffect[F].start(action).void

如果我像下面这样调用这个函数

for {
    _ <- service.seperateThread(request,languageId,cacheItinerary,slices,pricing)
} yield {}

它会在不同的 Fiber 中做 seperateThread 操作并立即返回 F[Unit] 还是等待操作完成?

解决方法

启动纤程是一个非阻塞操作,因此应用程序流将立即转到下一条指令。

为了等待另一个纤程中运行的操作完成,你需要调用纤程对象上的join操作。您无法在实现中执行此操作,因为您调用了 void,因此忽略了对 Fiber 的返回引用。

如果你像这样改变你的方法:

def seperateThread[F[_]: ConcurrentEffect: Functor: Sync](action: F[Unit]): F[Fiber[F,Unit]] = ConcurrentEffect[F].start(action)

然后您就可以使用对创建的光纤的引用到 join

for {
    fiber <- ConcurrentEffect[IO].start(IO(println("Hello from another fiber!")))
    // _ <- do some more operations in parallel ...
    result <- fiber.join //here you can access value returned by fiber 
                         //(in your case it's Unit so you can just ignore it).

} yield result

在大多数情况下不建议直接使用 Fiber 的 start,因为这可能导致资源泄漏。您应该考虑使用 background 代替它创建 Resource,它会在处理结束时自动取消和清理光纤。