简体   繁体   中英

Best way to call suspend coroutine from Executor(ThreadPoolExecutor)

I am currently developing face detection with with a camera library & mlkit.

Camera library provides a FrameProcessor in which I am getting Frame in a stream manner. I have written FrameProcessingTask inside a suspend function.

Inside cameralib FrameProcessor is called inside a 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();
                }
            });

In my side I have written:

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.
}

My question:

  1. is it right to use runBlocking inside Executor as it's called continuously in each frame.
  2. what happened to suspend runBlocking part if Executor canceled the task
  3. what happened if processor.process(frame); called again before frameProcessingTask finished it's task.
  1. is it right to use runBlocking inside Executor as it's called continuously in each frame.

If your code is being called as part of a blocking interface that expects the work to be done when the method returns, you don't have a choice but to block the thread until the work is done. The point of runBlocking is to enable calling suspend functions from this kind of places. FrameProcessor qualifies here.

  1. what happened to suspend runBlocking part if Executor canceled the task

If the task hasn't started yet, cancelling simply removes the task from the queue.

If the task has already completed, cancelling has no effect.

If the task is running, then the thread may be interrupted in an attempt to cancel the task (this depends on the mayInterruptIfRunning param used when cancelling the task).

In that last case, assuming the thread is already executing runBlocking , you can refer to the runBlocking documentation :

If this blocked thread is interrupted (see Thread.interrupt), then the coroutine job is cancelled and this runBlocking invocation throws InterruptedException.

So the answer is that your coroutine will be cancelled (which is probably what you expect).

  1. what happened if processor.process(frame); called again before frameProcessingTask finished it's task

It depends on mFrameProcessingExecutor . If it's multithreaded, then another task can be run in parallel of the previous one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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