繁体   English   中英

从 Executor(ThreadPoolExecutor) 调用挂起协程的最佳方法

[英]Best way to call suspend coroutine from Executor(ThreadPoolExecutor)

我目前正在使用相机库和 mlkit 开发人脸检测。

相机库提供了一个FrameProcessor ,我在其中以 stream 方式获取Frame 我在暂停 function 中编写了FrameProcessingTask

在 cameralib 内部FrameProcessorThreadPoolExecutor内部被调用

mFrameProcessingExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    for (FrameProcessor processor : mFrameProcessors) {
                        try {
                            processor.process(frame);
                        } catch (Exception e) {
                            LOG.w("Frame processor crashed:", e);
                        }
                    }
                    frame.release();
                }
            });

在我这边,我写道:

private val processor = FrameProcessor { frame ->
runBlocking { // used runBlocking to bridge suspend coroutine
    frameProcessingTask(frame)
    }
}

suspend fun frameProcessingTask(frame: Frame) = withContext(Dispatchers.Default)
 //face detection & processing code written here.
}

我的问题:

  1. Executor中使用runBlocking是否正确,因为它在每一帧中都被连续调用。
  2. 如果Executor取消任务,暂停runBlocking部分会发生什么
  3. 如果processor.process(frame);会发生什么? frameProcessingTask完成它的任务之前再次调用。
  1. 在 Executor 中使用 runBlocking 是否正确,因为它在每一帧中都被连续调用。

如果您的代码作为阻塞接口的一部分被调用,该接口期望在方法返回时完成工作,那么您别无选择,只能阻塞线程直到工作完成。 runBlocking的重点是允许从这种地方调用挂起函数。 FrameProcessor符合条件。

  1. 如果 Executor 取消任务,暂停 runBlocking 部分会发生什么

如果任务尚未开始,取消只是将任务从队列中删除。

如果任务已经完成,取消无效。

如果任务正在运行,则线程可能会被中断以尝试取消任务(这取决于取消任务时使用的mayInterruptIfRunning参数)。

在最后一种情况下,假设线程已经在执行runBlocking ,您可以参考runBlocking 文档

如果这个被阻塞的线程被中断(参见 Thread.interrupt),那么协程作业被取消并且这个 runBlocking 调用抛出 InterruptedException。

所以答案是你的协程将被取消(这可能是你所期望的)。

  1. 如果 processor.process(frame); 会发生什么? 在 frameProcessingTask 完成它的任务之前再次调用

它取决于mFrameProcessingExecutor 如果它是多线程的,那么另一个任务可以与前一个任务并行运行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM