我很高兴我切换了长期运行的任务,这些任务不断产生结果ui thread coroutines 。与Android中的异步箱或常规线相比,它提高了性能和减少记忆使用量3次,所有内存泄漏都消失了。
唯一的问题仍然是,我不知道在某些时候发生在异常之后的长期运行 ...
时,我应该如何重新启动长期运行的操作。我觉得在阅读了大量文章后,我根本不明白Coroutines中的例外处理。让我知道如何实现所需的行为。
- 我的碎片范围(将在不久的将来移至VM(。
​
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
}
我不知道我应该在哪里尝试捕获。我试图用try catch将deferred.await((包围,但是我可以在捕获块中调用相同的方法来重试长期运行任务。我尝试了 sustecorjob ((,但也没有成功。我仍然无法调用 initworkEngineCoroutine((再次和启动新的Coroutine ...
最终帮助解决此问题:(
您应该将代码视为线性命令,然后尝试/捕获在代码中最合乎逻辑的含义。有了这种思维方式,您的问题可能不再是关于Coroutines的,而更多地是关于尝试/捕捉重试。您可能会这样做:
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()
立即提出例外并最终导致无限循环引起的无限循环,从而导致意外行为和潜在的Stackoverflow。