我很高兴我将长时间运行的任务切换了,这些任务不断将 UI线程结果生成为协程。与AsyncTask或Android中的常规线程相比,它提高了性能并将内存使用量减少了3倍,并且所有内存泄漏都消失了。
唯一的问题是,我不知道在出现异常某个时候 ...
之后,我应该如何重新启动长时间运行的操作。阅读大量文章后,我觉得我根本不了解协程中的异常处理。让我知道如何实现期望的行为。
lateinit var initEngineJob: Job
override val coroutineContext: CoroutineContext
get() = initEngineJob + Dispatchers.Main
fun initWorkEngineCoroutine()
{
launch {
while(true) {
val deferred = async(Dispatchers.Default) {
getResultsFromEngine()
}
val result = deferred.await()
if (result != null) {
//UI thread
draw!!.showResult(result)
}
}
}
}
fun getResultsFromEngine() :Result? {
result = // some results from native c++ engine, which throws exception at some times
return result
}
我不知道应该在哪里抓鱼。我尝试将tryfer包围在deferred.await()中,但是我不能在catch块中调用相同的方法来重试长时间运行的任务。我尝试了 SupervisorJob (),但也没有成功。我仍然无法再次调用 initWorkEngineCoroutine()和启动新协程 ...
最终帮助解决此问题:)
答案 0 :(得分:3)
您应该将代码视为线性命令,并在代码中最合乎逻辑的地方尝试/捕获。有了这种心态,您的问题可能与协程无关,而与尝试/捕获重试有关。您可能会这样做:
fun main() {
GlobalScope.launch {
initWorkEngineCoroutine()
}
}
suspend fun initWorkEngineCoroutine() {
var failures = 0
val maxFailures = 3
while(failures <= maxFailures) {
try {
getResultsFromEngine()?.let {
draw!!.showResult(it)
}
} catch (e: Exception) {
failures++
}
}
}
// withContext is like async{}.await() except an exception occuring inside
// withContext can be caught from inside the coroutine.
// here, we are mapping getResultFromEngine() to a call to withContext and
// passing withContext the lambda which does the work
suspend fun getResultsFromEngine() :Result? = withContext(Dispatchers.Default) {
Result()
}
我提供了一些防止无限循环的逻辑。这可能不符合您的要求,但是您可能会考虑采取某种措施来防止getResultsFromEngine()
立即引发异常并最终导致无限循环的问题,该循环可能导致意外行为和潜在的堆栈溢出。 / p>