[英]Inappropriate blocking method call, but Suspend function 'withContext' should be called only from a coroutine or another suspend function
[英]Best way to call suspend coroutine from Executor(ThreadPoolExecutor)
我目前正在使用相机库和 mlkit 开发人脸检测。
相机库提供了一个FrameProcessor
,我在其中以 stream 方式获取Frame
。 我在暂停 function 中编写了FrameProcessingTask
。
在 cameralib 内部FrameProcessor
在ThreadPoolExecutor
内部被调用
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.
}
我的问题:
Executor
中使用runBlocking
是否正确,因为它在每一帧中都被连续调用。Executor
取消任务,暂停runBlocking
部分会发生什么processor.process(frame);
会发生什么? 在frameProcessingTask
完成它的任务之前再次调用。
- 在 Executor 中使用 runBlocking 是否正确,因为它在每一帧中都被连续调用。
如果您的代码作为阻塞接口的一部分被调用,该接口期望在方法返回时完成工作,那么您别无选择,只能阻塞线程直到工作完成。 runBlocking
的重点是允许从这种地方调用挂起函数。 FrameProcessor
符合条件。
- 如果 Executor 取消任务,暂停 runBlocking 部分会发生什么
如果任务尚未开始,取消只是将任务从队列中删除。
如果任务已经完成,取消无效。
如果任务正在运行,则线程可能会被中断以尝试取消任务(这取决于取消任务时使用的mayInterruptIfRunning参数)。
在最后一种情况下,假设线程已经在执行runBlocking
,您可以参考runBlocking
文档:
如果这个被阻塞的线程被中断(参见 Thread.interrupt),那么协程作业被取消并且这个 runBlocking 调用抛出 InterruptedException。
所以答案是你的协程将被取消(这可能是你所期望的)。
- 如果 processor.process(frame); 会发生什么? 在 frameProcessingTask 完成它的任务之前再次调用
它取决于mFrameProcessingExecutor
。 如果它是多线程的,那么另一个任务可以与前一个任务并行运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.