提问人:StayCool 提问时间:7/12/2023 最后编辑:JemshitStayCool 更新时间:7/12/2023 访问量:54
执行位图操作时 CoroutineWorker 中的 OOM
OOM in CoroutineWorker when doing Bitmap operations
问:
我正在尝试为一组文件(~2000)运行一些工作,我需要解码一些文件,因此需要大量内存。如果我像那样“做工作”:
override suspend fun doWork(): Result {
(0...2000).forEach { i ->
analyze(uris[i])
}
return Result.success()
}
fun analyze(uri) {
val bitmap = decodeBitmap(uri)
.onSuccess{
apply color filer()
}.onSuccess {
save bitmap to file system()
}
}
我在 10 秒内得到 OOM,因为解码、颜色过滤和保存是异步的,例如解码了 100 个位图,但只有 10 个经过颜色过滤,内存被位图溢出,然后我得到了 OOM。
有没有办法在不返回的情况下在 Worker 中运行异步操作? 我将所有流程都重新设计为递归,但似乎不可能在 Worker 中运行递归。也许有一些聪明的暂停方式?
答:
1赞
levi
7/12/2023
#1
您需要创建一个挂起函数,该函数在等待异步请求完成时暂停执行。目前,立即返回,这意味着 2000 个文件正在并行解码。analyze
analyze
可以使用 suspendCoroutine 来实现此目的。
suspend fun analyze() = suspendCoroutine { continuation ->
val bitmap = decodeBitmap(uri)
.onSuccess{
etc...
}.onSuccess {
continuation.resume()
}
}
评论
0赞
StayCool
7/13/2023
suspendCoroutine 没有成功,因为......要使用它,我必须为 2000 个文件中的每一个启动挂起协程?无论如何,它没有成功。但。
0赞
StayCool
7/13/2023
我用计数器 == 文件大小定义了 CountDownLatch,并将 ref of latch 传递给每个文件(这将在处理结束时 latch.countdown);我计算我通过了多少,有多少不是 countdowned(),如果这个值很大(例如,我启动了 50,但 latch 仍然是 200),所以我等到 latch 为 150 才能继续启动进程。这就像魅力一样,我现在可以控制我想使用多少 RAM(直到我得到 onLowMemory 回调或 OOM)
评论
decodeBitmap